gpt4 book ai didi

Java方法反射实现原理详解

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 25 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Java方法反射实现原理详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

博主说:java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为 java 语言的反射机制。在本文中,占小狼分析了 java 反射机制的实现原理(源码),感兴趣的同学可以通过阅读本文花上几分钟了解了解.

正文 。

Java方法反射实现原理详解

方法反射实例 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class reflectcase {
 
   public static void main(string[] args) throws exception {
     proxy target = new proxy();
     method method = proxy. class .getdeclaredmethod( "run" );
     method.invoke(target);
   }
 
   static class proxy {
     public void run() {
       system.out.println( "run" );
     }
   }
}

通过 java 的反射机制,可以在运行期间调用对象的任何方法,如果大量使用这种方式进行调用,会有性能或内存隐患么?为了彻底了解方法的反射机制,只能从底层代码入手啦! 。

method 获取 。

调用 class 类的getdeclaredmethod可以获取指定方法名和参数的方法对象 method.

getdeclaredmethod 。

Java方法反射实现原理详解

其中privategetdeclaredmethods方法从缓存或 jvm 中获取该 class 中申明的方法列表,searchmethods方法将从返回的方法列表里找到一个匹配名称和参数的方法对象.

searchmethods 。

Java方法反射实现原理详解

如果找到一个匹配的 method,则重新复制一份返回,即method.copy()方法.

Java方法反射实现原理详解

所次每次调用getdeclaredmethod方法返回的 method 对象其实都是一个新的对象,且新对象的root属性都指向原来的 method 对象,如果需要频繁调用,最好把 method 对象缓存起来.

privategetdeclaredmethods 。

从缓存或 jvm 中获取该 class 中申明的方法列表,实现如下:

Java方法反射实现原理详解

其中reflectiondata()方法实现如下:

Java方法反射实现原理详解

这里有个比较重要的数据结构reflectiondata,用来缓存从 jvm 中读取类的如下属性数据:

Java方法反射实现原理详解

从reflectiondata()方法实现可以看出:reflectiondata对象是softreference类型的,说明在内存紧张时可能会被回收,不过也可以通过-xx:softreflrupolicymspermb参数控制回收的时机,只要发生gc就会将其回收,如果reflectiondata被回收之后,又执行了反射方法,那只能通过newreflectiondata方法重新创建一个这样的对象了,newreflectiondata方法实现如下:

Java方法反射实现原理详解

通过unsafe.compareandswapobject方法重新设置reflectiondata字段;在privategetdeclaredmethods方法中,如果通过reflectiondata()获得的reflectiondata对象不为空,则尝试从reflectiondata对象中获取declaredmethods属性,如果是第一次,或则被gc回收之后,重新初始化后的类属性为空,则需要重新到 jvm 中获取一次,并赋值给reflectiondata,下次调用就可以使用缓存数据了.

method 调用 。

获取到指定的方法对象 method 之后,就可以调用它的invoke方法了,invoke实现如下:

Java方法反射实现原理详解

应该注意到:这里的methodaccessor对象是invoke方法实现的关键,一开始methodaccessor为空,需要调用acquiremethodaccessor生成一个新的methodaccessor对象,methodaccessor本身就是一个接口,实现如下:

Java方法反射实现原理详解

在acquiremethodaccessor方法中,会通过reflectionfactory类的newmethodaccessor创建一个实现了methodaccessor接口的对象,实现如下:

Java方法反射实现原理详解

在reflectionfactory类中,有 2 个重要的字段:noinflation(默认false)和inflationthreshold(默认15),在checkinitted方法中可以通过-dsun.reflect.inflationthreshold=xxx和-dsun.reflect.noinflation=true对这两个字段重新设置,而且只会设置一次;如果noinflation为false,方法newmethodaccessor都会返回delegatingmethodaccessorimpl对象,delegatingmethodaccessorimpl的类实现:

Java方法反射实现原理详解

其实,delegatingmethodaccessorimpl对象就是一个代理对象,负责调用被代理对象delegate的invoke方法,其中delegate参数目前是nativemethodaccessorimpl对象,所以最终 method 的invoke方法调用的是nativemethodaccessorimpl对象invoke方法,实现如下:

Java方法反射实现原理详解

这里用到了reflectionfactory类中的inflationthreshold,当delegate调用了15次invoke方法之后,如果继续调用就通过methodaccessorgenerator类的generatemethod方法生成methodaccessorimpl对象,并设置为delegate对象,这样下次执行method.invoke时,就调用新建的methodaccessor对象的invoke()方法了。这里需要注意的是:generatemethod方法在生成methodaccessorimpl对象时,会在内存中生成对应的字节码,并调用classdefiner.defineclass创建对应的 class 对象,实现如下:

Java方法反射实现原理详解

在classdefiner.defineclass方法实现中,每被调用一次都会生成一个delegatingclassloader类加载器对象:

Java方法反射实现原理详解

这里每次都生成新的类加载器,是为了性能考虑,在某些情况下可以卸载这些生成的类,因为类的卸载是只有在类加载器可以被回收的情况下才会被回收的,如果用了原来的类加载器,那可能导致这些新创建的类一直无法被卸载,从其设计来看本身就不希望这些类一直存在内存里的,在需要的时候有就行啦! 。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.

原文链接:http://www.jianshu.com/p/3ea4a6b57f87 。

最后此篇关于Java方法反射实现原理详解的文章就讲到这里了,如果你想了解更多关于Java方法反射实现原理详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com