MethodHandle查找工具



就JavaDoc而言,MethodHandles.lookup()返回能够访问与该函数调用者相同的方法/函数/构造函数的设施。具体来说,如果调用者可以访问一些私有数据,比如这个MethodHandles。查找设备。下面的代码证明这是错误的。我哪里说错了?

public class MethodHandlerAccessTest  {
        private static class NestedClass {
            private static void foo(){}
        }
        @Test
        public void testPrivateAccess() throws Throwable {
            NestedClass.foo();  //compiles and executes perfectly
            MethodType type = MethodType.methodType(void.class);
            MethodHandles.Lookup lookup = MethodHandles.lookup();
            MethodHandle mh = lookup.findStatic(NestedClass.class, "foo", type);
        }
 }
编辑:

这是我得到的:

. lang。非法访问异常:成员是私有的:MethodHandlerAccessTest NestedClass.foo美元()无效,MethodHandlerAccessTest在java.lang.invoke.MemberName.makeAccessException (MemberName.java: 507)在java.lang.invoke.MethodHandles Lookup.checkAccess美元(MethodHandles.java: 1182)在java.lang.invoke.MethodHandles Lookup.checkMethod美元(MethodHandles.java: 1162)在java.lang.invoke.MethodHandles Lookup.accessStatic美元(MethodHandles.java: 591)在java.lang.invoke.MethodHandles Lookup.findStatic美元(MethodHandles.java: 587)在MethodHandlerAccessTest.testPrivateAccess (MethodHandlerAccessTest.java: 19)在sun.reflect.NativeMethodAccessorImpl。invoke0(本机方法)atsun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java: 57)在sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java: 43)java.lang.reflect.Method.invoke(Method.java:601org.junit.runners.model.FrameworkMethod runreflectivecall 1.美元(FrameworkMethod.java: 47)在org.junit.internal.runners.model.ReflectiveCallable.run (ReflectiveCallable.java: 12)在org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.java: 44)在org.junit.internal.runners.statements.InvokeMethod.evaluate (InvokeMethod.java: 17)在org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) atorg.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java: 70)在org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java: 50)在org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) atorg.junit.runners.ParentRunner时间表(ParentRunner.java: 63) 1.美元org.junit.runners.ParentRunner.runChildren (ParentRunner.java: 236)org.junit.runners.ParentRunner.access 000美元(ParentRunner.java: 53)org.junit.runners.ParentRunner评估(ParentRunner.java: 229) 2.美元org.junit.runners.ParentRunner.run (ParentRunner.java: 309)org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run (JUnit4TestReference.java: 50)在org.eclipse.jdt.internal.junit.runner.TestExecution.run (TestExecution.java: 38)在org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (RemoteTestRunner.java: 467)在org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (RemoteTestRunner.java: 683)在org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run (RemoteTestRunner.java: 390)在org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main (RemoteTestRunner.java: 197)

问题是您的测试方法没有真正调用NestedClass.foo()。这条线:

NestedClass.foo();

…实际上转换为对foo中生成的合成方法的调用,如下所示:

NestedClass.access$000();

access$000看起来像这样:

// Note package access
static void access$000() {
    foo();
}

您可以通过使用javap -c查看实际的字节码来验证这一点。

在JVM级别,外部类没有访问foo()的权限。Java编译器通过创建access$000并在源代码调用foo()时从外部类调用它来合成对它的访问。

在执行时,反射库做同样的事情,因此你的错误。

相关内容

  • 没有找到相关文章

最新更新