Jdk反射优化

使用 JDK 的动态代理时,会使用反射调用方法。但相比于正常调用方法,利用反射的性能要低一些,通过测试,我们可以看到Jdk内部对反射调用进行了优化。

如果jdk>=9的话,需添加下面的vm option参数。

复制代码
--add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/jdk.internal.reflect=ALL-UNNAMED

package com.example.demo2.b09;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestMethodInvoke {
    public static void main(String[] args) throws Exception {
        Method foo = TestMethodInvoke.class.getMethod("foo", int.class);

        for(int i = 1; i <= 17; i++){
            show(i, foo);
            foo.invoke(null, i);
        }
        System.in.read();
    }

    private static void show(int i, Method foo) throws Exception {
        Method getMethodAccessor = Method.class.getDeclaredMethod("getMethodAccessor");
        getMethodAccessor.setAccessible(true);
        Object invoke = getMethodAccessor.invoke(foo);
        if (invoke == null) {
            System.out.println(i + ":" + null);
            return;
        }
        // DelegatingMethodAccessorImpl 的全限定类名(不同版本的 JDK 存在差异)
        Field delegate = Class.forName("sun.reflect.DelegatingMethodAccessorImpl").getDeclaredField("delegate");
        delegate.setAccessible(true);
        System.out.println(i + ": " + delegate.get(invoke));
    }

    public static void foo(int i){
        System.out.println(i + ":" + "foo");
    }
}

输出结果:

复制代码
1: null
1: foo
2: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
2: foo
3: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
3: foo
4: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
4: foo
5: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
5: foo
6: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
6: foo
7: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
7: foo
8: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
8: foo
9: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
9: foo
10: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
10: foo
11: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
11: foo
12: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
12: foo
13: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
13: foo
14: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
14: foo
15: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
15: foo
16: sun.reflect.NativeMethodAccessorImpl@1be6f5c3
16: foo
17: sun.reflect.GeneratedMethodAccessor2@5b2133b1
17: foo

通过结果可以知道,前16次jdk使用的是本地的MethodAccessor实现反射调用,后面一次进行了优化,使用的是GeneratedMethodAccessor2进行调用,通过Arthas工具可以看到该类的实现,里面是正常调用foo方法,没有使用反射,提高了性能。

相关推荐
皮皮林5518 小时前
Java性能调优黑科技!1行代码实现毫秒级耗时追踪,效率飙升300%!
java
冰_河8 小时前
QPS从300到3100:我靠一行代码让接口性能暴涨10倍,系统性能原地起飞!!
java·后端·性能优化
桦说编程11 小时前
从 ForkJoinPool 的 Compensate 看并发框架的线程补偿思想
java·后端·源码阅读
躺平大鹅12 小时前
Java面向对象入门(类与对象,新手秒懂)
java
初次攀爬者13 小时前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺13 小时前
搞懂@Autowired 与@Resuorce
java·spring boot·后端
Derek_Smart15 小时前
从一次 OOM 事故说起:打造生产级的 JVM 健康检查组件
java·jvm·spring boot
NE_STOP16 小时前
MyBatis-mybatis入门与增删改查
java
孟陬19 小时前
国外技术周刊 #1:Paul Graham 重新分享最受欢迎的文章《创作者的品味》、本周被划线最多 YouTube《如何在 19 分钟内学会 AI》、为何我不
java·前端·后端