// proxy
cv.visitField(ACC_PRIVATE, IH_FIELD, Type.getDescriptor(InvocationHandler.class), null, null);
// create a static adapter for generating a static initialiser method in
// the generated subclass
staticAdapter = new GeneratorAdapter(ACC_STATIC,
new Method("<clinit>", Type.VOID_TYPE, NO_ARGS), null, null, cv);
// add a zero args constructor method
Method m = new Method("<init>", Type.VOID_TYPE, NO_ARGS);
GeneratorAdapter methodAdapter = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cv);
// loadthis
methodAdapter.loadThis();
// List the constructors in the superclass.
Constructor<?>[] constructors = superclassClass.getDeclaredConstructors();
// Check that we've got at least one constructor, and get the 1st one in the list.
if (constructors.length > 0) {
// We now need to construct the proxy class as though it is going to invoke the superclasses constructor.
// We do this because we can no longer call the java.lang.Object() zero arg constructor as the JVM now throws a VerifyError.
// So what we do is build up the calling of the superclasses constructor using nulls and default values. This means that the
// class bytes can be verified by the JVM, and then in the ProxySubclassGenerator, we load the class without invoking the
// constructor.
Method constructor = Method.getMethod(constructors[0].toGenericString());
Type[] argTypes = constructor.getArgumentTypes();
if (argTypes.length == 0) {
methodAdapter.invokeConstructor(Type.getType(superclassClass), new Method("<init>", Type.VOID_TYPE, NO_ARGS));
} else {
for (Type type : argTypes) {
switch (type.getSort())
{
case Type.ARRAY:
// We need to process any array or multidimentional arrays.
String elementDesc = type.getElementType().getDescriptor();
String typeDesc = type.getDescriptor();
// Iterate over the number of arrays and load 0 for each one. Keep a count of the number of
// arrays as we will need to run different code fo multi dimentional arrays.
int index = 0;
while (! elementDesc.equals(typeDesc)) {
typeDesc = typeDesc.substring(1);
methodAdapter.visitInsn(Opcodes.ICONST_0);
index++;
}
// If we're just a single array, then call the newArray method, otherwise use the MultiANewArray instruction.
if (index == 1) {
methodAdapter.newArray(type.getElementType());
} else {
methodAdapter.visitMultiANewArrayInsn(type.getDescriptor(), index);
}
break;
case Type.BOOLEAN:
methodAdapter.push(true);
break;
case Type.BYTE:
methodAdapter.push(Type.VOID_TYPE);
break;
case Type.CHAR:
methodAdapter.push(Type.VOID_TYPE);
break;
case Type.DOUBLE:
methodAdapter.push(0.0);
break;
case Type.FLOAT:
methodAdapter.push(0.0f);
break;
case Type.INT:
methodAdapter.push(0);
break;
case Type.LONG:
methodAdapter.push(0l);
break;
case Type.SHORT:
methodAdapter.push(0);
break;
default:
case Type.OBJECT:
methodAdapter.visitInsn(Opcodes.ACONST_NULL);
break;
}
}
methodAdapter.invokeConstructor(Type.getType(superclassClass), new Method("<init>", Type.VOID_TYPE, argTypes));
}
}
methodAdapter.returnValue();
methodAdapter.endMethod();
// add a method for getting the invocation handler
Method setter = new Method("setInvocationHandler", Type.VOID_TYPE, new Type[] { IH_TYPE });
m = new Method("getInvocationHandler", IH_TYPE, NO_ARGS);
methodAdapter = new GeneratorAdapter(ACC_PUBLIC | ACC_FINAL, m, null, null, cv);
// load this to get the field
methodAdapter.loadThis();
// get the ih field and return
methodAdapter.getField(newClassType, IH_FIELD, IH_TYPE);
methodAdapter.returnValue();
methodAdapter.endMethod();
// add a method for setting the invocation handler
methodAdapter = new GeneratorAdapter(ACC_PUBLIC | ACC_FINAL, setter, null, null, cv);
// load this to put the field
methodAdapter.loadThis();
// load the method arguments (i.e. the invocation handler) to the stack
methodAdapter.loadArgs();
// set the ih field using the method argument
methodAdapter.putField(newClassType, IH_FIELD, IH_TYPE);
methodAdapter.returnValue();
methodAdapter.endMethod();
// loop through the class hierarchy to get any needed methods off the
// supertypes
// start by finding the methods declared on the class of interest (the
// superclass of our dynamic subclass)