JVM

JVM05 JVM是如何实现反射的?

2018-12-19  本文已影响13人  夜阑人儿未静

什么是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生成策略

上一篇下一篇

猜你喜欢

热点阅读