使用bcel动态创建class

博客介绍了Apache的BCEL库,指出使用其进行动态构建类工作,关键在于了解Java的class结构。作者因有大量.NET反编译工作经验,使用BCEL不感困难,并提供了使用BCEL创建类实例而非反射的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Apache的BCEL库,文档很少,例子也很简单。动态构建类的工作,要求的只是并不是熟练使用BCEL类库本身,而是要对java的class结构了解。我对java的pcode也不熟悉,但是我曾经做过大量的.NET的反编译工作,两者类似,所以我用BCEL也不觉得困难。

我提供一个例子,这里例子是使用BCEL创建类的实例,而不是使用反射。

如下:

IFactory.java

ExpandedBlockStart.gifContractedBlock.gifpublic interface IFactory dot.gif{
InBlock.gif    
public Object newInstance();    
ExpandedBlockEnd.gif}

FileClassLoader.java
None.gifimport java.io.ByteArrayOutputStream;
None.gifimport java.io.File;
None.gifimport java.io.FileInputStream;
None.gifimport java.io.IOException;
None.gif
ExpandedBlockStart.gifContractedBlock.gif
public class FileClassLoader extends ClassLoader dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public FileClassLoader() dot.gif{
InBlock.gif        super();
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public FileClassLoader(ClassLoader parent) dot.gif{
InBlock.gif        super(parent);
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public Class getClass(String className, String filePath) dot.gif{
InBlock.gif        FileInputStream fileInputStream 
= null;
InBlock.gif        
byte[] data = null;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
try dot.gif{
InBlock.gif            fileInputStream 
= new FileInputStream(new File(filePath));
InBlock.gif
InBlock.gif            ByteArrayOutputStream byteArrayOutputStream 
= new ByteArrayOutputStream();
InBlock.gif            
int ch = 0;
ExpandedSubBlockStart.gifContractedSubBlock.gif            
while ((ch = fileInputStream.read()) != -1dot.gif{
InBlock.gif                byteArrayOutputStream.write(ch);
ExpandedSubBlockEnd.gif            }

InBlock.gif            data 
= byteArrayOutputStream.toByteArray();
InBlock.gif            
return defineClass(className, data, 0, data.length);
ExpandedSubBlockStart.gifContractedSubBlock.gif        }
 catch (IOException e) dot.gif{
InBlock.gif            e.printStackTrace();
InBlock.gif            
throw new Error(e.getMessage(), e);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

buildFactory方法:
None.gifpublic static IFactory buildFactory(String procductClassName)
ExpandedBlockStart.gifContractedBlock.gif        throws Exception 
dot.gif{
InBlock.gif    InstructionList il 
= new InstructionList();
InBlock.gif    String className 
= "HelloWorld";
InBlock.gif    ClassGen class_gen 
= new ClassGen(className, "java.lang.Object",
InBlock.gif            
"", Constants.ACC_PUBLIC | Constants.ACC_SUPER, null);
InBlock.gif    ConstantPoolGen cons_pool 
= class_gen.getConstantPool();
InBlock.gif    class_gen.addInterface(IFactory.
class.getName());
InBlock.gif
InBlock.gif    InstructionFactory il_factory 
= new InstructionFactory(class_gen);
InBlock.gif
InBlock.gif    
// 创建构造函数
ExpandedSubBlockStart.gifContractedSubBlock.gif
    dot.gif{
InBlock.gif        String methodName 
= "";
InBlock.gif
InBlock.gif        Type returnType 
= Type.VOID;
ExpandedSubBlockStart.gifContractedSubBlock.gif        Type[] arg_Types 
= new Type[] dot.gif{};
ExpandedSubBlockStart.gifContractedSubBlock.gif        String[] arg_names 
= new String[] dot.gif{};
InBlock.gif        MethodGen method_gen 
= new MethodGen(Constants.ACC_PUBLIC,
InBlock.gif                returnType, arg_Types, arg_names, methodName, className,
InBlock.gif                il, cons_pool);
InBlock.gif
InBlock.gif        
// super();
InBlock.gif
        il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
InBlock.gif        il.append(il_factory.createInvoke(
"java.lang.Object""",
InBlock.gif                Type.VOID, 
new Type[0], Constants.INVOKESPECIAL));
InBlock.gif        il.append(InstructionFactory.createReturn(Type.VOID));
InBlock.gif
InBlock.gif        method_gen.setMaxStack();
InBlock.gif        class_gen.addMethod(method_gen.getMethod());
InBlock.gif        il.dispose(); 
// Reuse instruction handles of list
ExpandedSubBlockEnd.gif
    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        String methodName 
= "newInstance";
InBlock.gif        Type returnType 
= Type.OBJECT;
ExpandedSubBlockStart.gifContractedSubBlock.gif        Type[] arg_Types 
= new Type[] dot.gif{};
ExpandedSubBlockStart.gifContractedSubBlock.gif        String[] arg_names 
= new String[] dot.gif{};
InBlock.gif        MethodGen method_gen 
= new MethodGen(Constants.ACC_PUBLIC,
InBlock.gif                returnType, arg_Types, arg_names, methodName, className,
InBlock.gif                il, cons_pool);
InBlock.gif        il.append(il_factory.createNew(procductClassName));
InBlock.gif        il.append(InstructionConstants.DUP);
InBlock.gif        il.append(il_factory.createInvoke(procductClassName, 
"",
InBlock.gif                Type.VOID, 
new Type[0], Constants.INVOKESPECIAL));
InBlock.gif        il.append(InstructionFactory.createReturn(Type.OBJECT));
InBlock.gif        method_gen.setMaxStack();
InBlock.gif
InBlock.gif        class_gen.addMethod(method_gen.getMethod());
InBlock.gif        il.dispose(); 
// Reuse instruction handles of list
ExpandedSubBlockEnd.gif
    }

InBlock.gif
InBlock.gif    
// 保存到文件中
InBlock.gif
    JavaClass clazz = class_gen.getJavaClass();
InBlock.gif    String path 
= "e:\\temp\\" + className + ".class";
InBlock.gif    class_gen.getJavaClass().dump(path);
InBlock.gif
InBlock.gif    
// 使用ClassLoader装载class
InBlock.gif
    FileClassLoader classLoader = new FileClassLoader();
InBlock.gif    Class factoryClass 
= classLoader.getClass(className, path);
InBlock.gif    Object newInst 
= factoryClass.newInstance();
InBlock.gif
InBlock.gif    
return (IFactory) newInst;
ExpandedBlockEnd.gif}

测试用例:
None.gifString className = "java.lang.Object";
None.gifIFactory factory 
= buildFactory(className);
None.gifObject inst 
= factory.newInstance();
None.gif
3297.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值