反射调用
反射:
在程序运行时,另一种方式的调用构造方法,方法,字段的行为。应用在框架,java集成开发环境idea中。
方法反射调用的实现:
method实例指向方法的地址值(类加载到虚拟机中,方法会加载到方法区,有明确的地址),反射调用传入准备好的参数,调用进入目标方法。
每次调用invoke,都会通过一个委派实现调用本地方法实现反射调用。当调用达到一定的次数(15次)之后,就会动态生成字节码实现(相当于生成了一个类),下次调用的时候,委派实现就会调用这个动态实现去完成方法的调用。
本地方法实现和动态实现的切换过程叫做inflation。可通过参数-Dsun.reflect.noInflation=true进行开启与关闭
反射调用的开销
class.forName调用本地方法
占用堆内存,是的GC频繁。(invoke()是个变长参数方法Obeject数组,每次都要生成新的数组。)
即时编译优化方法内联:反射调用被内联了,即时编译的逃逸分析将新建的Objec数组判定为不会逃逸对象,因此不会触发垃圾回收。假设invoke()方法外创建数组,无法优化访问数组的操作。
基本数组类型拆箱装箱(Objec数组,基本类型要拆箱装箱)
java缓存了-128到127,还可手动调整缓存范围
本地方法实现消耗性能
关闭反射调用inflation机制。
方法多个有不同的动态实现,可能会造成方法内联的失效,逃逸分析不再起作用。
生产环境有多个不同的动态实现,对于 invokevirtual 或者 invokeinterface,Java 虚拟机会记录下调用者的具体类型(称之为类型 profile),java虚拟机无法同时记录这么多类,可能会造成方法内联失效,逃逸分析不再起效
方法内联:指的是编译器在编译一个方法时,将某个方法调用的目标方法也纳入编译范围内,并用其返回值替代原方法调用这么个过程

浙公网安备 33010602011771号