使用bcel动态创建class

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

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

如下:

IFactory.java

public interface IFactory {
    
public Object newInstance();    
}

FileClassLoader.java
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class FileClassLoader extends ClassLoader {
    
public FileClassLoader() {
        super();
    }


    
public FileClassLoader(ClassLoader parent) {
        super(parent);
    }


    
public Class getClass(String className, String filePath) {
        FileInputStream fileInputStream 
= null;
        
byte[] data = null;
        
try {
            fileInputStream 
= new FileInputStream(new File(filePath));

            ByteArrayOutputStream byteArrayOutputStream 
= new ByteArrayOutputStream();
            
int ch = 0;
            
while ((ch = fileInputStream.read()) != -1{
                byteArrayOutputStream.write(ch);
            }

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

    }

}

buildFactory方法:
public static IFactory buildFactory(String procductClassName)
        throws Exception 
{
    InstructionList il 
= new InstructionList();
    String className 
= "HelloWorld";
    ClassGen class_gen 
= new ClassGen(className, "java.lang.Object",
            
"", Constants.ACC_PUBLIC | Constants.ACC_SUPER, null);
    ConstantPoolGen cons_pool 
= class_gen.getConstantPool();
    class_gen.addInterface(IFactory.
class.getName());

    InstructionFactory il_factory 
= new InstructionFactory(class_gen);

    
// 创建构造函数
    {
        String methodName 
= "";

        Type returnType 
= Type.VOID;
        Type[] arg_Types 
= new Type[] {};
        String[] arg_names 
= new String[] {};
        MethodGen method_gen 
= new MethodGen(Constants.ACC_PUBLIC,
                returnType, arg_Types, arg_names, methodName, className,
                il, cons_pool);

        
// super();
        il.append(InstructionFactory.createLoad(Type.OBJECT, 0));
        il.append(il_factory.createInvoke(
"java.lang.Object""",
                Type.VOID, 
new Type[0], Constants.INVOKESPECIAL));
        il.append(InstructionFactory.createReturn(Type.VOID));

        method_gen.setMaxStack();
        class_gen.addMethod(method_gen.getMethod());
        il.dispose(); 
// Reuse instruction handles of list
    }


    
{
        String methodName 
= "newInstance";
        Type returnType 
= Type.OBJECT;
        Type[] arg_Types 
= new Type[] {};
        String[] arg_names 
= new String[] {};
        MethodGen method_gen 
= new MethodGen(Constants.ACC_PUBLIC,
                returnType, arg_Types, arg_names, methodName, className,
                il, cons_pool);
        il.append(il_factory.createNew(procductClassName));
        il.append(InstructionConstants.DUP);
        il.append(il_factory.createInvoke(procductClassName, 
"",
                Type.VOID, 
new Type[0], Constants.INVOKESPECIAL));
        il.append(InstructionFactory.createReturn(Type.OBJECT));
        method_gen.setMaxStack();

        class_gen.addMethod(method_gen.getMethod());
        il.dispose(); 
// Reuse instruction handles of list
    }


    
// 保存到文件中
    JavaClass clazz = class_gen.getJavaClass();
    String path 
= "e:\\temp\\" + className + ".class";
    class_gen.getJavaClass().dump(path);

    
// 使用ClassLoader装载class
    FileClassLoader classLoader = new FileClassLoader();
    Class factoryClass 
= classLoader.getClass(className, path);
    Object newInst 
= factoryClass.newInstance();

    
return (IFactory) newInst;
}

测试用例:
String className = "java.lang.Object";
IFactory factory 
= buildFactory(className);
Object inst 
= factory.newInstance();

posted on 2005-04-14 23:59  温少  阅读(3118)  评论(2编辑  收藏  举报

导航