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方法,没有使用反射,提高了性能。

相关推荐
nice_lcj5201 小时前
Java Lambda 表达式入门:怎么写、怎么用、常用方法有哪些
java·开发语言·后端·面试
码农小河662 小时前
基于SSM+JSP+MySQL的在线医疗服务系统的设计与实现
java·开发语言·mysql
SL_staff3 小时前
从配置失效到逻辑复用:JVS-Logic 如何构建可治理的业务编排中枢
java·spring·产品
特立独行的猫A3 小时前
一份 Markdown 发十个平台:cspub 一稿多投
java·后端·python
文丑颜不良啊4 小时前
LeetCode1961~1980题目解析
java·leetcode
文丑颜不良啊4 小时前
LeetCode2001~2020题目解析
java·leetcode
用户3721574261354 小时前
Java 批量提取 Word 文档中的图片并保存到本地
java
SL_staff5 小时前
BI项目失败率90%?JVS如何用三阶闭环构建可落地的数据生产力平台
java·开源·全栈
nice_lcj5206 小时前
ThreadLocal 入门:它是怎么隔离数据的、为什么会导致内存泄漏
java·开发语言·后端·面试·并发编程·内存泄漏·threadlocal
紧跟先前的步伐6 小时前
Go AI Agent 实战 28|Agent 的预算、超时与停止条件
开发语言·人工智能·后端·ai·golang