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 方式启动目标类
- 启动HSDB
- attach 到目标进程上
- 在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);
}
}
作者: 吴炼钿