浅析Java方法反射原理

    技术2025-04-11  9

    1. 前言

    1.1 目标

    java程序员日常开发经常使用到反射技术,所以本文就是要讲解一下java的方法反射,让大家更好了解反射的性能.

    1.2 反射性能结论

    默认配置下,前15次的反射方法会通过native方法执行,在native方法中,如本方法是热点,是无法有效的内联优化 ,而且在native方法中要检查及组装方法参数,最后动态执行,也进一步影响性能 。默认配置下,超过15次后,会通过字节码生成对应代理类,间接调用目标方法.这种实现方式可接近直接调用方法的性能,缺点使用字节码生成代理类要耗性能及在运行时会多加载一个类

    2. 代码示例

    2.1 示例代码

    public class ReflectionTest { public static int count =0; public void test(){ new Exception((count++)+" : print stackTrace ").printStackTrace(); } public static void main(String[] args) throws Exception { ReflectionTest test = new ReflectionTest(); Method method = test.getClass().getMethod("test"); for(int i=0;i<20;i++){ method.invoke(test); } } }

    2.2 打印结果

    ... java.lang.Exception: 14 : print stackTrace at reflection1.ReflectionTest.test(ReflectionTest.java:8) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at reflection1.ReflectionTest.main(ReflectionTest.java:15) java.lang.Exception: 15 : print stackTrace at reflection1.ReflectionTest.test(ReflectionTest.java:8) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at reflection1.ReflectionTest.main(ReflectionTest.java:15) java.lang.Exception: 16 : print stackTrace at reflection1.ReflectionTest.test(ReflectionTest.java:8) at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at reflection1.ReflectionTest.main(ReflectionTest.java:15)

    注意 第11行与第18行的栈调用链是不同的,11行的invoke还是NativeMethodAccessorImpl实现的,而18行是通过GeneratedMethodAccessor1实现的

    3. 流程概要分析

    3.1 概要流程

    3.1.1 设置-Dsun.reflect.noInflation=true

    如果启动参数设置了-Dsun.reflect.noInflation=true则每次调用method.invoke()都会生成代理类,并间接调用目标方法 jvm默认的设置为-Dsun.reflect.noInflation=false

    3.1.2 调用native方法实现反射

    如果method.invoke()执行次数<=15次(具体多少次可由sun.reflect.inflationThreshold决定,默认是15次) 从2.2的打印结果中可以从栈信息中看出: 前15次都是通过调用:sun.reflect.NativeMethodAccessorImpl.invoke0这个方法实现反射的,其代码如下:

    private static native Object invoke0(Method m, Object obj, Object[] args);

    从声明上可以看出是个本地方法,具体在代码分析阶段会分析到

    3.1.3 生成代理类,间接调用ReflectionTest.test方法

    如果method.invoke()执行次数>15次,则与设置了sun.reflect.noInflation=true一样,会通过字节码生成代理类,通过代理类间接调用目标方法. 其调用链条为: Method.invoke()->DelegatingMethodAccessorImpl.invoke()->GeneratedMethodAccessor1.invoke() ->目标方法

    具体查看所生成的代理类的方法如下:

    debug 方式启动目标类启动HSDBattach 到目标进程上在HSDB上 Class Browser上查找到GeneratedMethodAccessor1类,并点击:Create .class File 这连接 在本地用户 下的sun/reflect/目录下可以找到GeneratedMethodAccessor1.class,并将其反编译一下,如果如下: package sun.reflect; import java.lang.reflect.InvocationTargetException; public class GeneratedMethodAccessor1 extends MethodAccessorImpl { public Object invoke(Object var1, Object[] var2) throws InvocationTargetException { if (var1 == null) { throw new NullPointerException(); } else { ReflectionTest var10000; try { var10000 = (ReflectionTest)var1; if (var2 != null && var2.length != 0) { throw new IllegalArgumentException(); } } catch (NullPointerException | ClassCastException var4) { throw new IllegalArgumentException(var4.toString()); } try { var10000.test(); return null; } catch (Throwable var3) { throw new InvocationTargetException(var3); } } } public GeneratedMethodAccessor1() { } }

    4. 代码分析

    4.1 Method.invoke()方法 分析

    反射的主要逻辑是如果MethodAccessor对象为空,则通过acquireMethodAccessor()创建一个. 然后调用MethodAccessor对象的invoke()方法实现反射调用.

    public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { Class<?> caller = Reflection.getCallerClass(); checkAccess(caller, clazz, obj, modifiers); } } MethodAccessor ma = methodAccessor; if (ma == null) { ma = acquireMethodAccessor();//见:4.1.1.acquireMethodAccessor方法 } return ma.invoke(obj, args); }

    4.1.1 Method.acquireMethodAccessor方法

    MethodAccessor对象主要由reflectionFactory.newMethodAccessor(this)实现

    private MethodAccessor acquireMethodAccessor() { // First check to see if one has been created yet, and take it // if so MethodAccessor tmp = null; if (root != null) tmp = root.getMethodAccessor();//最开始是空 if (tmp != null) { methodAccessor = tmp; } else { // Otherwise fabricate one and propagate it up to the root tmp = reflectionFactory.newMethodAccessor(this);//创建methodAccessor对象,见 4.1.2 newMethodAccessor方法 setMethodAccessor(tmp); } return tmp; }

    4.1.2 ReflectionFactory.newMethodAccessor

    当sun.reflect.noInflation=false时,会创建出MethodAccessor的实现类DelegatingMethodAccessorImpl, Method.invoke()方法主要调用的是DelegatingMethodAccessorImpl的invoke()方法. 而DelegatingMethodAccessorImpl的invoke()方法执行的其delegate.invoke()方法 在当前的方法中delegate指向的是NativeMethodAccessorImpl对象 NativeMethodAccessorImpl类的invoke实现可见 4.1.3 NativeMethodAccessorImpl.invoke

    public MethodAccessor newMethodAccessor(Method method) { checkInitted(); if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {//设置-Dsun.reflect.noInflation=true才会执行 return new MethodAccessorGenerator(). generateMethod(method.getDeclaringClass(), method.getName(), method.getParameterTypes(), method.getReturnType(), method.getExceptionTypes(), method.getModifiers()); } else { NativeMethodAccessorImpl acc = new NativeMethodAccessorImpl(method); DelegatingMethodAccessorImpl res = new DelegatingMethodAccessorImpl(acc);//后面的invoke就是调用本类的 acc.setParent(res); return res; } }

    4.1.3 NativeMethodAccessorImpl.invoke

    从代码上可以看出,如果本方法重复执行大于15,则会将其父类即DelegatingMethodAccessorImpl的delegate类换成由MethodAccessorGenerator产生的字节码

    public Object invoke(Object obj, Object[] args) throws IllegalArgumentException, InvocationTargetException { if (++numInvocations > ReflectionFactory.inflationThreshold() //默认15 && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) { MethodAccessorImpl acc = (MethodAccessorImpl) new MethodAccessorGenerator(). generateMethod(method.getDeclaringClass(), method.getName(), method.getParameterTypes(), method.getReturnType(), method.getExceptionTypes(), method.getModifiers()); parent.setDelegate(acc); } return invoke0(method, obj, args);//本地类 }

    4.2 NativeMethodAccessorImpl.invoke0方法

    NativeMethodAccessorImpl.invoke0方法是本地方法,按java jni的习惯规则,我们可以在/jdk/src/share/native/sun/reflect/目录下找到NativeAccessors.c,再根据:"包名_类名_方法名"规则找到方法,其代码实现如下:

    JNIEXPORT jobject JNICALL Java_sun_reflect_NativeMethodAccessorImpl_invoke0 (JNIEnv *env, jclass unused, jobject m, jobject obj, jobjectArray args) { return JVM_InvokeMethod(env, m, obj, args); }

    然后调用 jvm.cpp的下面方法

    JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0)) JVMWrapper("JVM_InvokeMethod"); Handle method_handle; if (thread->stack_available((address) &method_handle) >= JVMInvokeMethodSlack) { method_handle = Handle(THREAD, JNIHandles::resolve(method)); Handle receiver(THREAD, JNIHandles::resolve(obj)); objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0))); //反射调用主要是调用下面方法实现的 oop result = Reflection::invoke_method(method_handle(), receiver, args, CHECK_NULL); jobject res = JNIHandles::make_local(env, result); if (JvmtiExport::should_post_vm_object_alloc()) { oop ret_type = java_lang_reflect_Method::return_type(method_handle()); assert(ret_type != NULL, "sanity check: ret_type oop must not be NULL!"); if (java_lang_Class::is_primitive(ret_type)) { JvmtiExport::post_vm_object_alloc(JavaThread::current(), result); } } return res; } else { THROW_0(vmSymbols::java_lang_StackOverflowError()); } JVM_END

    4.2.1 Reflection::invoke_method

    reflection.cpp的invoke_method方法

    oop Reflection::invoke_method(oop method_mirror, Handle receiver, objArrayHandle args, TRAPS) { oop mirror = java_lang_reflect_Method::clazz(method_mirror); int slot = java_lang_reflect_Method::slot(method_mirror); bool override = java_lang_reflect_Method::override(method_mirror) != 0; objArrayHandle ptypes(THREAD, objArrayOop(java_lang_reflect_Method::parameter_types(method_mirror))); oop return_type_mirror = java_lang_reflect_Method::return_type(method_mirror); BasicType rtype; if (java_lang_Class::is_primitive(return_type_mirror)) { rtype = basic_type_mirror_to_basic_type(return_type_mirror, CHECK_NULL); } else { rtype = T_OBJECT; } instanceKlassHandle klass(THREAD, java_lang_Class::as_Klass(mirror)); //取得Method对象 Method* m = klass->method_with_idnum(slot); if (m == NULL) { THROW_MSG_0(vmSymbols::java_lang_InternalError(), "invoke"); } methodHandle method(THREAD, m); //主要的逻辑在invoke方法 return invoke(klass, method, receiver, override, ptypes, rtype, args, true, THREAD); }

    4.2.1 Reflection::invoke

    oop Reflection::invoke(instanceKlassHandle klass, methodHandle reflected_method, Handle receiver, bool override, objArrayHandle ptypes, BasicType rtype, objArrayHandle args, bool is_method_invoke, TRAPS) { ResourceMark rm(THREAD); methodHandle method; // actual method to invoke KlassHandle target_klass; // target klass, receiver's klass for non-static // Ensure klass is initialized klass->initialize(CHECK_NULL); bool is_static = reflected_method->is_static(); if (is_static) { // ignore receiver argument method = reflected_method; target_klass = klass; } else { // check for null receiver if (receiver.is_null()) { THROW_0(vmSymbols::java_lang_NullPointerException()); } // Check class of receiver against class declaring method if (!receiver->is_a(klass())) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "object is not an instance of declaring class"); } // target klass is receiver's klass target_klass = KlassHandle(THREAD, receiver->klass()); // no need to resolve if method is private or <init> if (reflected_method->is_private() || reflected_method->name() == vmSymbols::object_initializer_name()) { method = reflected_method; } else { //如果是接口方法,则执行如下逻辑 if (reflected_method->method_holder()->is_interface()) { // resolve interface call if (ReflectionWrapResolutionErrors) { method = resolve_interface_call(klass, reflected_method, target_klass, receiver, THREAD); if (HAS_PENDING_EXCEPTION) { oop resolution_exception = PENDING_EXCEPTION; CLEAR_PENDING_EXCEPTION; JavaCallArguments args(Handle(THREAD, resolution_exception)); THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(), vmSymbols::throwable_void_signature(), &args); } } else { method = resolve_interface_call(klass, reflected_method, target_klass, receiver, CHECK_(NULL)); } } else { //否则通过查询虚方法表vtable来确定最终的方法 assert(!reflected_method->has_itable_index(), ""); int index = reflected_method->vtable_index(); method = reflected_method; if (index != Method::nonvirtual_vtable_index) { InstanceKlass* inst = (InstanceKlass*)target_klass(); method = methodHandle(THREAD, inst->method_at_vtable(index)); } if (!method.is_null()) { // Check for abstract methods as well if (method->is_abstract()) { // new default: 6531596 if (ReflectionWrapResolutionErrors) { ResourceMark rm(THREAD); Handle h_origexception = Exceptions::new_exception(THREAD, vmSymbols::java_lang_AbstractMethodError(), Method::name_and_sig_as_C_string(target_klass(), method->name(), method->signature())); JavaCallArguments args(h_origexception); THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(), vmSymbols::throwable_void_signature(), &args); } else { ResourceMark rm(THREAD); THROW_MSG_0(vmSymbols::java_lang_AbstractMethodError(), Method::name_and_sig_as_C_string(target_klass(), method->name(), method->signature())); } } } } } } if (method.is_null()) { ResourceMark rm(THREAD); THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), Method::name_and_sig_as_C_string(klass(), reflected_method->name(), reflected_method->signature())); } if (!(JDK_Version::is_gte_jdk14x_version() && UseNewReflection)) { if (!override) { if (!(klass->is_public() && reflected_method->is_public())) { bool access = Reflection::reflect_check_access(klass(), reflected_method->access_flags(), target_klass(), is_method_invoke, CHECK_NULL); if (!access) { return NULL; // exception } } } } // !(Universe::is_gte_jdk14x_version() && UseNewReflection) assert(ptypes->is_objArray(), "just checking"); int args_len = args.is_null() ? 0 : args->length(); // Check number of arguments if (ptypes->length() != args_len) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "wrong number of arguments"); } // Create object to contain parameters for the JavaCall JavaCallArguments java_args(method->size_of_parameters()); if (!is_static) { java_args.push_oop(receiver); } //如果反射的方法有参加,则把参数加入到java_args中 for (int i = 0; i < args_len; i++) { oop type_mirror = ptypes->obj_at(i); oop arg = args->obj_at(i); //如果是基本类型,按如下处理 if (java_lang_Class::is_primitive(type_mirror)) { jvalue value; BasicType ptype = basic_type_mirror_to_basic_type(type_mirror, CHECK_NULL); BasicType atype = unbox_for_primitive(arg, &value, CHECK_NULL); if (ptype != atype) { widen(&value, atype, ptype, CHECK_NULL); } switch (ptype) { case T_BOOLEAN: java_args.push_int(value.z); break; case T_CHAR: java_args.push_int(value.c); break; case T_BYTE: java_args.push_int(value.b); break; case T_SHORT: java_args.push_int(value.s); break; case T_INT: java_args.push_int(value.i); break; case T_LONG: java_args.push_long(value.j); break; case T_FLOAT: java_args.push_float(value.f); break; case T_DOUBLE: java_args.push_double(value.d); break; default: THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch"); } } else { if (arg != NULL) { Klass* k = java_lang_Class::as_Klass(type_mirror); if (!arg->is_a(k)) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "argument type mismatch"); } } Handle arg_handle(THREAD, arg); // Create handle for argument java_args.push_oop(arg_handle); // Push handle } } assert(java_args.size_of_parameters() == method->size_of_parameters(), "just checking"); JavaValue result(rtype); //最终调用JavaCalls::call执行 JavaCalls::call(&result, method, &java_args, THREAD); if (HAS_PENDING_EXCEPTION) { // Method threw an exception; wrap it in an InvocationTargetException oop target_exception = PENDING_EXCEPTION; CLEAR_PENDING_EXCEPTION; JavaCallArguments args(Handle(THREAD, target_exception)); THROW_ARG_0(vmSymbols::java_lang_reflect_InvocationTargetException(), vmSymbols::throwable_void_signature(), &args); } else { if (rtype == T_BOOLEAN || rtype == T_BYTE || rtype == T_CHAR || rtype == T_SHORT) narrow((jvalue*) result.get_value_addr(), rtype, CHECK_NULL); return box((jvalue*) result.get_value_addr(), rtype, CHECK_NULL); } }

    作者: 吴炼钿

    Processed: 0.009, SQL: 9