以下论点均基于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类中字段的多少并不会显著的影响性能。
那么来到第二个问题针对反射方法而言有哪些方式可以优化呢?