以下论点均基于jdk8但大部分并不限于jdk8

openjdk version "1.8.0_382-internal"
OpenJDK Runtime Environment (build 1.8.0_382-internal-b05)
OpenJDK 64-Bit Server VM (build 25.382-b05, mixed mode)

首先让我们从两个问题出发

1.使用field和get set方法访问修改字段值哪个的性能要更好(均已做了缓存)?

2.怎么优化一个反射方法?

以下为一个简单jmh基准测试结果:

获取字段值方式                           Mode  Cnt  Score   Error  Units
直接获取                                avgt   60  2.011 ± 0.074  ns/op
使用field获取                           avgt   60  3.642 ± 0.219  ns/op
使用get method获取                      avgt   60  4.237 ± 0.113  ns/op
修改字段值方式                           Mode  Cnt  Score   Error  Units
直接修改                                avgt   60  2.855 ± 0.026  ns/op
使用field修改                           avgt   60  5.289 ± 0.241  ns/op
使用set method修改                      avgt   60  6.226 ± 0.253  ns/op

ps: 上述method的性能为Inflation后的性能,反射调用method超过InflationThreshold(默认15)后 会生成sun.reflect.GeneratedMethodAccessor,在类和字段较多时可能会导致metaSpace OOM (当设置了MaxMetaSpaceSize参数时),可以关闭Inflation机制但会带来性能较为明显的下降.

所以第一个问题的结论就是field的性能要更好,且field不会动态生成类对metaSpace的压力更小,因此如果只是为了获取字段值,field方式始终优于get set方法

值得一提的还有不管是field还是method类中字段的多少并不会显著的影响性能。

那么来到第二个问题针对反射方法而言有哪些方式可以优化呢?

  1. 字节码生成
  2. MethodHandle(方法句柄)
  3. LambdaMetafactory