[フレーム]
Last Updated: February 25, 2016
·
4.487K
· eller86

Generate class dynamically with ObjectWeb ASM

At first, you have to create byte array (= contents in .class file) with ClassWriter.

private byte[] createClassBinary() {
 ClassWriter cw = new ClassWriter(0);
 cw.visit(V1_5, ACC_PUBLIC, "pkg/OwnClass", null, "java/lang/Object", null);
 {
 // constructor
 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
 mv.visitMaxs(2, 1);
 mv.visitVarInsn(ALOAD, 0); // push `this` to the operand stack
 mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V"); // call the constructor of super class
 mv.visitInsn(RETURN);
 mv.visitEnd();
 }
 {
 // public Object get() { return new Object(); }
 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "get", "()Ljava/lang/Object;", null, null);
 mv.visitMaxs(2, 1);
 mv.visitTypeInsn(NEW, Type.getInternalName(Object.class));
 mv.visitInsn(DUP);
 mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V");
 mv.visitInsn(ARETURN);
 mv.visitEnd();
 }
 cw.visitEnd();
 return cw.toByteArray();
}

Then, you can create Class instance from this byte array. You have to create original Class loader and call its #defineClass method.

private static class OwnClassLoader extends ClassLoader {
 public Class<?> defineClass(String name, byte[] b) {
 return defineClass(name, b, 0, b.length);
 }
}

private Class<?> createClass(byte[] b) {
 return new OwnClassLoader().defineClass("pkg.OwnClass", b);
}

AltStyle によって変換されたページ (->オリジナル) /