JVM05 JVM是如何实现反射的?
什么是Java的反射机制?
java的反射机制是在运行状态中,对于任意一个类(Class)都能知道他的属性(Field)和方法(Method),对于任意一个对象都能够调用它的方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。它允许正在运行的java程序观测甚至是修改程序的动态行为。
反射的实现方式有哪些?
1、通过Class.forName()方法加载字符串
Class<?> clazz = Class.forName("java.lang.String")
2、通过类名调用class属性得到该类的Class对象
Class<?> clazz = String.class
3、调用实例的getClass()方法
Class<?> clazz = date.getClass()
4、如果是基本类型的包装类,则可以通过调用包装类的Type属性来获得该包装类的Class对象
反射调用是怎么实现的?
查阅 Method.invoke 的源代码发现,它实际上委派给 MethodAccessor 来处理。
public final class Method extends Executable {
...
public Object invoke(Object obj, Object... args) throws ... {
... // 权限检查
MethodAccessor ma = methodAccessor;
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
}
MethodAccessor 是一个接口,它有两个实现:一个通过本地方法来实现反射调用,另一个使用了委派模式(委派实现)。
在默认情况下,方法的反射调用为委派实现,委派给本地实现来进行方法调用。在调用超过 15 次之后,委派实现便会将委派对象切换至动态实现。这个动态实现的字节码是自动生成的,它将直接使用 invoke 指令来调用目标方法。
反射调用带来哪些性能开销?
1、接口的通用性,java的invoke方法是传object和object[]数组的。基本参数类型需要装箱和拆箱,产生大量额外的对象和内存开销,频繁促发GC。
2、编译器难以对动态调用的代码提前做优化比如方法内联。
3、反射需要按名检索类和方法,有一定的时间开销。
反射在java中的应用有哪些?
1、java集成开发环境,每当我们敲入点号时,IDE便会根据点号前的内容,动态展示可以访问的字段和方法。
2、java调试器,它能够在调试过程中枚举某一对象所有字段的值。
3、web开发中,我们经常接触到各种配置的通用框架。为保证框架的可扩展性,他往往借助java的反射机制。例如Spring框架的依赖反转(IOC)便是依赖于反射机制。
4、AOP拦截获取方法信息。典型的例子:Spring缓存@Cacheable的key生成策略