jvm和反射
仅作为作者学习笔记
前言
仅作为作者学习笔记
一、反射的基本实现
反射有两种实现方式:
- 本地方法调用(就是字节码中已经定义好的方法)
- 动态生成字节码
两者有什么区别?
- 动态生成字节码(以下简称动态实现),生成字节码的过程很慢(类似于准备工作),但是执行效率高。
- 本地方法调用,不用生成字节码,直接调用本地方法。所以准备工作几乎没有,很快。但是执行效率就差很多。
JVM如何做决定选择哪种实现方式?
动态实现和本地实现相比,其运行效率要快上 20 倍 。这是因为动态实现无需经过 Java 到 C++ 再到 Java 的切换,但由于生成字节码十分耗时,仅调用一次的话,反而是本地实现要快上 3 到 4 倍 。考虑到许多反射调用仅会执行一次,Java 虚拟机设置了一个阈值 15(可以通过 -Dsun.reflect.inflationThreshold= 来调整),当某个反射调用的调用次数在 15 之下时,采用本地实现;当达到 15 时,便开始动态生成字节码,并将委派实现的委派对象切换至动态实现,这个过程我们称之为 Inflation。
- 通过反射执行的次数来决定,默认值是15。15次之前直接本地调用,之后动态实现。
JVM为啥分两种实现方式?
- 本地实现的调用流程复杂。而在执行多次的情况下,复杂意味着性能损耗,所以有一种适合多次执行的解决方案,就是动态生成字节码。
反射的缺点原因?
- 方法的反射调用会带来不少性能开销,原因主要有三个:变长参数方法导致的 Object 数组,基本类型的自动装箱、拆箱,还有最重要的方法内联。