美文网首页
JVM中是如何实现反射的

JVM中是如何实现反射的

作者: lhsjohn | 来源:发表于2019-05-29 17:53 被阅读0次

前言1: 反射常用的API介绍:

获取class对象

  1. 调用静态方法Class.forName来获取
  2. 调用对象的getClass()方法
  3. 直接调用类名 + ".class"访问。对于基本类型而言,它们的包装类型拥有一个名为‘TYPE'的final静态字段,指向该基本类型对应的Class对象

例如,Integer.TYPE指向int.class.对于数组类型来说,可以使用类名 + "[].class"来访问,例如int[].class

一旦获取到Class对象,我们便可以正式的使用反射功能了,常用的几项:

  1. 使用newintznce()来生成一个该类的实例。它要求该类中拥有一个无参数的构造器。

  2. 使用isInstance(Object)来判断一个对象是否为该类的实例,语法上等同于instance of

  3. 使用Array.newInstance(Class,int) 来构建该类型的数组

  4. 使用getFIleds()/getConstructors()/getMethods()来访问该类的成员。方法名中带Declared的不会返回父类的成员,但是会返回私有成员,而带有Declared的则相反。

当获得了类成员之后,我们可以进一步的操作

  1. 使用Construct/Field/Method.setAccessible(true) 来绕开Java语言的访问限制
  2. 使用Construct.newInstance(Object[])来生成该类的实例
  3. 使用Field.get()/set(Object)来访问字段的值
  4. 使用Method.invoke(Object,Object[])来调用方法

前言2:内联的概念解释

方法内联指的是编译器在编译一个方法时,将某个方法调用的目标方法也纳入编译范围内,并用返回值 替代方法调用的过程。

接下来聊一聊反射

反射机制在java中的应用: ide的提示功能、java调试器,一些可配置的通用框架为了保证其可扩展性,往往借助Java的反射机制根据配置文件加载不同的类。例如Spring框架的依赖反转(ioc)便是依赖于反射机制。

但是反射机制也有它显著的缺点:性能开销大

那么反射是怎么实现的呢?看一看Method.invoke()的调用

查阅Method.invoke的源代码可以发现,它实际上会委托给MethodAccessor来处理。MethodAccessor是一个接口,它有两个具体的实现:一个通过本地方法实现反射,另一个则使用了委派模式。

每个Method实例的第一次反射调用都会生成一个委派实现,它所委派的具体实现便是一个本地实现。本地实现非常容易理解,当进入了java虚拟机内部的时候,我们便拥有了Method实例所指向方法的具体地址,这时候反射调用无非就是将传入的参数准备好,然后调用进入目标方法。

打印反射调用的栈轨迹可以发现,反射调用先是调用了Method.invoke,然后进入委派实现(DelegatingMethodAccessorImpl),再然后进入本地方法实现(NativeMethodAccessorImpl)最后到达目标方法.

那么,为什么反射调用还要采取委派实现作为中间层?直接交给本地实现不可以吗?

其实,java反射调用机制还设立了另一种动态生成字节码的实现(动态实现),直接使用invoke指令来调用目标方法,之所以采用委派实现,便是为了能够在本地实现以及动态实现中切换。(可以联想动态代理的invoke)

动态实现与本地实现相比,运行效率要快上20倍,因为动态实现无需经过java到c++再到java的切换,但由于生成字节码十分耗时,仅调用一次的话,反而使用本地实现要快上3到4倍。

考虑到许多反射调用仅会执行一次,java虚拟机设置了一个阈值15(-Dsun.reflect.inflationThreshold= ? )来调整,当某个反射调用的调用次数在15次之下的时候,采用本地实现,当达到15时,便开始动态生成字节码,并将委派实现的委派对象切换至动态实现,这个过程称之为inflation.

总结一下反射调用的性能开销

方法的反射调用会带来不少的性能开销,原因主要有三个,变长参数方法导致的Object数组,基本类型的自动装箱、拆箱还有最重要的方法内联。

以上内容是我对极客时间郑雨迪老师<<深入拆解Java虚拟机>>的精简版总结。

相关文章

  • JVM中是如何实现反射的

    前言1: 反射常用的API介绍: 获取class对象 调用静态方法Class.forName来获取 调用对象的ge...

  • JVM是如何实现Java反射的?

    Java的反射应用场景非常多,例如IDE在做联想时,Spring的IoC容器等等。通过反射,我们可以做一些平时做不...

  • 07 JVM 是如何实现反射的

    Java 中的反射 反射是 Java 语言的一个相当重要的特性,它允许正在运行的 Java 程序观测,甚至是修改程...

  • JVM05 JVM是如何实现反射的?

    什么是Java的反射机制?java的反射机制是在运行状态中,对于任意一个类(Class)都能知道他的属性(Fiel...

  • JVM深度剖析:JVM是如何实现反射的?

    反射是 Java 语言中一个相当重要的特性,它允许正在运行的 Java 程序观测,甚至是修改程序的动态行为。 举例...

  • Class对象的一些概念

    最近在写动态代理的demo,反射是动态代理的核心实现,而反射是通过jvm中的class对象在运行期动态调用任意一个...

  • JVM的反射实现

    java的反射机制 java的反射机制是在运行状态中,对于任意一个类(Class)都能知道他的属性(Field)和...

  • JVM的反射调用实现

    如何执行反射调用 Java的反射调用是通过java.lang.reflect.Method的invoke调用执行,...

  • Java反射详解

    一、什么是反射? “反射(Reflection)能够让运行于JVM中的程序检测和修改运行时的行为。反射用于在运行时...

  • Java 反射详解

    什么是反射? 反射(Reflection)能够让运行于 JVM 中的程序检测和修改运行时的行为。 Class 类 ...

网友评论

      本文标题:JVM中是如何实现反射的

      本文链接:https://www.haomeiwen.com/subject/hiqutctx.html