public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { Class<?> caller = Reflection.getCallerClass(); checkAccess(caller, clazz, Modifier.isStatic(modifiers) ? null : obj.getClass(), modifiers); } MethodAccessorma= methodAccessor; // read volatile if (ma == null) { // 获取访问器 ma = acquireMethodAccessor(); } return ma.invoke(obj, args); }
acquireMethodAccessor
invoke内部使用了代理,先生成一个Accessor代理对象,然后调用代理对象执行代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
private MethodAccessor acquireMethodAccessor() { // First check to see if one has been created yet, and take it // if so MethodAccessortmp=null; if (root != null) tmp = root.getMethodAccessor(); if (tmp != null) { methodAccessor = tmp; } else { // 创建accessor tmp = reflectionFactory.newMethodAccessor(this); setMethodAccessor(tmp); }
// 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] "jdk/internal/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
shortnumCPEntries= NUM_BASE_CPOOL_ENTRIES + NUM_COMMON_CPOOL_ENTRIES; booleanusesPrimitives= 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());
// Output class information for non-primitive parameter types nonPrimitiveParametersBaseIdx = add(asm.cpi(), S2); for (inti=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(); }
// Load class vec.trim(); finalbyte[] 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 AccessController.doPrivileged( newPrivilegedAction<MagicAccessorImpl>() { @SuppressWarnings("deprecation")// Class.newInstance public MagicAccessorImpl run() { try { return (MagicAccessorImpl) ClassDefiner.defineClass (generatedName, bytes, 0, bytes.length, declaringClass.getClassLoader()).newInstance(); } catch (InstantiationException | IllegalAccessException e) { thrownewInternalError(e); } } }); }