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();
