How could I add a new constructor to a class?
I am migrating an old framework that used ow2.asm extensively for unit tests from Java 7 to Java 11. It creates "proxy" classes on the fly based from an interface. My problem is that it now fails when it tries to add a constructor and I'm not sure how ow2.asm is supposed to add constructors in the first place.
Here's a minimal trace of how this framework uses ow2.asm. I've ensured that the framework is using v8.0.1 (updated from version 5):
// We start with this method which abstracts the creation of proxy classes
// from the given interface.
defineProxyClass(Class<?> interf, String packageName, String clazzName) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
// some strings are constructed
// The code does this but I think this can be ignored in new Java versions?
ClassVisitor cv = cw;
// I'm unsure if these calls are relevant
cv.visit(51, Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, fullClazzName, null, "java/lang/Object",
new String[] { interfInternalName } // Interfaces
);
// Add field that holds reference to proxied object
cv.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, "proxiedObject", Type.getType(interf).getDescriptor(), null,
null);
// This is the problematic method
addConstructor(cv, fullClazzName, interfInternalName);
// Nothing more relevant follows, as far as I can tell
}
Now the problematic method does as follows:
void addConstructor(ClassVisitor cv, String clazzIntName, String paramDesc) {
// This is the constructor this is supposed to create and add
MethodVisitor mv = cv.visitMethod(1, "<init>", "(L" + paramDesc + ";)V", (String)null, (String[])null);
mv.visitCode();
mv.visitVarInsn(25, 0);
mv.visitMethodInsn(183, "java/lang/Object", "<init>", "()V", false);
mv.visitVarInsn(25, 0);
mv.visitVarInsn(25, 1);
mv.visitFieldInsn(181, clazzIntName, "proxiedObject", "L" + paramDesc + ";");
mv.visitInsn(177);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
Now, it seems to me that this code is "incomplete"; the addConstructor
method visits/creates the desired constructor but does not actually "add" them to cv
. Is the call to visitMethod
above enough?
I tried adding a call to ClassWriter.newMethod
but the resulting test error just changed but I think it's just my ignorance in using newMethod
properly. Are there examples available of what I am trying to achieve? Is this possible with ow2.asm at all?