Java 方法句柄的疑问

2020-05-14 14:30:48 +08:00
 jinzhongyuan

MethodHandles.lookup().findSpecial() 不能获取私有方法的方法句柄嘛?

user 类

public class User {
    private String name;

    public User(String name) {
        this.name = name;
    }

    public void speck(String msg) {
        System.out.println(name + "在说:" + msg);
    }

    private void sing() {
        System.out.println(name + "在私有方法里唱歌");
    }
}

测试类

public class 句柄测试 {
    @SneakyThrows
    @Test
    public void 句柄测试() {
        User user = new User("张三");

        MethodHandles.Lookup lookup = MethodHandles.lookup();

        MethodHandle speckMethodHandle = lookup.findVirtual(User.class, "speck", MethodType.methodType(void.class, String.class));

        //此处执行没问题,"speck" 是 public 方法
        speckMethodHandle.invokeExact(user, "今天天气不错");

        //此处报错
        MethodHandle singMethodHandle = lookup.findSpecial(User.class, "sing", MethodType.methodType(void.class), User.class);

        singMethodHandle.invokeExact(user);
    }
}

报错信息

java.lang.IllegalAccessException: no private access for invokespecial: class com.yjz.jvm.反射.jdk7 方法句柄.User, from com.yjz.jvm.反射.jdk7 方法句柄.句柄测试

	at java.lang.invoke.MemberName.makeAccessException(MemberName.java:850)
	at java.lang.invoke.MethodHandles$Lookup.checkSpecialCaller(MethodHandles.java:1572)
	at java.lang.invoke.MethodHandles$Lookup.findSpecial(MethodHandles.java:1002)
	at com.yjz.jvm.反射.jdk7 方法句柄.句柄测试.句柄测试(句柄测试.java:24)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)

Disconnected from the target VM, address: '127.0.0.1:50979', transport: 'socket'

Process finished with exit code -1

我看网上博客说 MethodHandles.lookup().findSpecial() 可以获取私有方法的句柄,但是测试下来不可以?

哪位知道是啥原因?如果不可以,那我怎么获取私有方法句柄?

1306 次点击
所在节点    Java
26 条回复
yukiloh
2020-05-14 16:54:25 +08:00
涨姿势了
句柄可以理解为引用的吧
jinzhongyuan
2020-05-14 16:56:18 +08:00
@yukiloh 我也不是很懂,但是 api 用下来的感觉就是引用,句柄引用 Method 类
wangyanrui
2020-05-14 17:14:25 +08:00
方法句柄是为了 invokedynamic 而生的, 你用方法句柄的 findSpecial(),其实底层还是走的 invokespecial 指令
jinzhongyuan
2020-05-14 17:18:45 +08:00
@wangyanrui 现实中使用方法句柄的场景多吗 /
wangyanrui
2020-05-14 17:26:22 +08:00
@jinzhongyuan 不敢回复,不知道多不多,反正我是没用过😂😂
jinzhongyuan
2020-05-14 17:28:47 +08:00
@wangyanrui 好吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/671606

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX