/** This routine is not thread-safe */ private MagicAccessorImpl generate( final Class declaringClass, String name, Class[] parameterTypes, Class returnType, Class[] checkedExceptions, int modifiers, boolean isConstructor, boolean forSerialization, Class serializationTargetClass) { ByteVector vec = ByteVectorFactory.create(); asm = new ClassFileAssembler(vec); this.declaringClass = declaringClass; this.parameterTypes = parameterTypes; this.returnType = returnType; this.modifiers = modifiers; this.isConstructor = isConstructor; this.forSerialization = forSerialization; asm.emitMagicAndVersion(); // Constant pool entries: // ( * = Boxing information: optional) // (+ = Shared entries provided by AccessorGenerator) // (^ = Only present if generating SerializationConstructorAccessor) // [UTF-8] [This class's name] // [CONSTANT_Class_info] for above // [UTF-8] // "sun/reflect/{MethodAccessorImpl,ConstructorAccessorImpl,SerializationConstructorAccessorImpl}" // [CONSTANT_Class_info] for above // [UTF-8] [Target class's name] // [CONSTANT_Class_info] for above // ^ [UTF-8] [Serialization: Class's name in which to invoke constructor] // ^ [CONSTANT_Class_info] for above // [UTF-8] target method or constructor name // [UTF-8] target method or constructor signature // [CONSTANT_NameAndType_info] for above // [CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info] for target method // [UTF-8] "invoke" or "newInstance" // [UTF-8] invoke or newInstance descriptor // [UTF-8] descriptor for type of non-primitive parameter 1 // [CONSTANT_Class_info] for type of non-primitive parameter 1 // ... // [UTF-8] descriptor for type of non-primitive parameter n // [CONSTANT_Class_info] for type of non-primitive parameter n // + [UTF-8] "java/lang/Exception" // + [CONSTANT_Class_info] for above // + [UTF-8] "java/lang/ClassCastException" // + [CONSTANT_Class_info] for above // + [UTF-8] "java/lang/NullPointerException" // + [CONSTANT_Class_info] for above // + [UTF-8] "java/lang/IllegalArgumentException" // + [CONSTANT_Class_info] for above // + [UTF-8] "java/lang/InvocationTargetException" // + [CONSTANT_Class_info] for above // + [UTF-8] "<init>" // + [UTF-8] "()V" // + [CONSTANT_NameAndType_info] for above // + [CONSTANT_Methodref_info] for NullPointerException's constructor // + [CONSTANT_Methodref_info] for IllegalArgumentException's constructor // + [UTF-8] "(Ljava/lang/String;)V" // + [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V" // + [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String // + [UTF-8] "(Ljava/lang/Throwable;)V" // + [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V" // + [CONSTANT_Methodref_info] for InvocationTargetException's constructor // + [CONSTANT_Methodref_info] for "super()" // + [UTF-8] "java/lang/Object" // + [CONSTANT_Class_info] for above // + [UTF-8] "toString" // + [UTF-8] "()Ljava/lang/String;" // + [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;" // + [CONSTANT_Methodref_info] for Object's toString method // + [UTF-8] "Code" // + [UTF-8] "Exceptions" // * [UTF-8] "java/lang/Boolean" // * [CONSTANT_Class_info] for above // * [UTF-8] "(Z)V" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "booleanValue" // * [UTF-8] "()Z" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "java/lang/Byte" // * [CONSTANT_Class_info] for above // * [UTF-8] "(B)V" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "byteValue" // * [UTF-8] "()B" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "java/lang/Character" // * [CONSTANT_Class_info] for above // * [UTF-8] "(C)V" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "charValue" // * [UTF-8] "()C" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "java/lang/Double" // * [CONSTANT_Class_info] for above // * [UTF-8] "(D)V" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "doubleValue" // * [UTF-8] "()D" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "java/lang/Float" // * [CONSTANT_Class_info] for above // * [UTF-8] "(F)V" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "floatValue" // * [UTF-8] "()F" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "java/lang/Integer" // * [CONSTANT_Class_info] for above // * [UTF-8] "(I)V" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "intValue" // * [UTF-8] "()I" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "java/lang/Long" // * [CONSTANT_Class_info] for above // * [UTF-8] "(J)V" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "longValue" // * [UTF-8] "()J" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "java/lang/Short" // * [CONSTANT_Class_info] for above // * [UTF-8] "(S)V" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "shortValue" // * [UTF-8] "()S" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above short numCPEntries = NUM_BASE_CPOOL_ENTRIES + NUM_COMMON_CPOOL_ENTRIES; boolean usesPrimitives = usesPrimitiveTypes(); if (usesPrimitives) { numCPEntries += NUM_BOXING_CPOOL_ENTRIES; } if (forSerialization) { numCPEntries += NUM_SERIALIZATION_CPOOL_ENTRIES; } // Add in variable-length number of entries to be able to describe // non-primitive parameter types and checked exceptions. numCPEntries += (short) (2 * numNonPrimitiveParameterTypes()); asm.emitShort(add(numCPEntries, S1)); final String generatedName = generateName(isConstructor, forSerialization); asm.emitConstantPoolUTF8(generatedName); asm.emitConstantPoolClass(asm.cpi()); thisClass = asm.cpi(); if (isConstructor) { if (forSerialization) { asm.emitConstantPoolUTF8("sun/reflect/SerializationConstructorAccessorImpl"); } else { asm.emitConstantPoolUTF8("sun/reflect/ConstructorAccessorImpl"); } } else { asm.emitConstantPoolUTF8("sun/reflect/MethodAccessorImpl"); } asm.emitConstantPoolClass(asm.cpi()); superClass = asm.cpi(); asm.emitConstantPoolUTF8(getClassName(declaringClass, false)); asm.emitConstantPoolClass(asm.cpi()); targetClass = asm.cpi(); short serializationTargetClassIdx = (short) 0; if (forSerialization) { asm.emitConstantPoolUTF8(getClassName(serializationTargetClass, false)); asm.emitConstantPoolClass(asm.cpi()); serializationTargetClassIdx = asm.cpi(); } asm.emitConstantPoolUTF8(name); asm.emitConstantPoolUTF8(buildInternalSignature()); asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); if (isInterface()) { asm.emitConstantPoolInterfaceMethodref(targetClass, asm.cpi()); } else { if (forSerialization) { asm.emitConstantPoolMethodref(serializationTargetClassIdx, asm.cpi()); } else { asm.emitConstantPoolMethodref(targetClass, asm.cpi()); } } targetMethodRef = asm.cpi(); if (isConstructor) { asm.emitConstantPoolUTF8("newInstance"); } else { asm.emitConstantPoolUTF8("invoke"); } invokeIdx = asm.cpi(); if (isConstructor) { asm.emitConstantPoolUTF8("([Ljava/lang/Object;)Ljava/lang/Object;"); } else { asm.emitConstantPoolUTF8("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"); } invokeDescriptorIdx = asm.cpi(); // Output class information for non-primitive parameter types nonPrimitiveParametersBaseIdx = add(asm.cpi(), S2); for (int i = 0; i < parameterTypes.length; i++) { Class c = parameterTypes[i]; if (!isPrimitive(c)) { asm.emitConstantPoolUTF8(getClassName(c, false)); asm.emitConstantPoolClass(asm.cpi()); } } // Entries common to FieldAccessor, MethodAccessor and ConstructorAccessor emitCommonConstantPoolEntries(); // Boxing entries if (usesPrimitives) { emitBoxingContantPoolEntries(); } if (asm.cpi() != numCPEntries) { throw new InternalError( "Adjust this code (cpi = " + asm.cpi() + ", numCPEntries = " + numCPEntries + ")"); } // Access flags asm.emitShort(ACC_PUBLIC); // This class asm.emitShort(thisClass); // Superclass asm.emitShort(superClass); // Interfaces count and interfaces asm.emitShort(S0); // Fields count and fields asm.emitShort(S0); // Methods count and methods asm.emitShort(NUM_METHODS); emitConstructor(); emitInvoke(); // Additional attributes (none) asm.emitShort(S0); // Load class vec.trim(); final byte[] bytes = vec.getData(); // Note: the class loader is the only thing that really matters // here -- it's important to get the generated code into the // same namespace as the target class. Since the generated code // is privileged anyway, the protection domain probably doesn't // matter. return (MagicAccessorImpl) AccessController.doPrivileged( new PrivilegedAction() { public Object run() { try { return ClassDefiner.defineClass( generatedName, bytes, 0, bytes.length, declaringClass.getClassLoader()) .newInstance(); } catch (InstantiationException e) { throw (InternalError) new InternalError().initCause(e); } catch (IllegalAccessException e) { throw (InternalError) new InternalError().initCause(e); } } }); }