Handle Lookup Method of the Object

As for the JavaDoc states, MethodHandles.lookup() returns an object that has the ability to access the same method / functions / constructor as the calling object of this function. In particular, if the caller can access some personal data, as this is MethodHandles.Lookup. The code below demonstrates that this is not true. Where am I mistaken?

 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); } } 

Edit:

This is what I get:

java.lang.IllegalAccessException: member closed: HandlerAccessTest method $ NestedClass.foo () void, from the HandlerAccessTest method on java.lang.invoke.MemberName.makeAccessException (MemberName.java:507) in java.lang.invoke.MethodHandccess $ Lookup.checheck $ Lookupcheckck MethodHandles.java:1182) in java.lang.invoke.MethodHandles $ Lookup.checkMethod (MethodHandles.java:1162) in java.lang.invoke.MethodHandles $ Lookup.accessStatic (MethodHandles.javahaps91) in java.lang.invoke .MethodHandles $ Lookup.findStatic (MethodHandles.javaPoint87) at MethodHandlerAccessTest.testPrivateAccess (MethodHandlerAccessTest.java:19) at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method) in sun.reflect.NativeMethodAccessorploplccessPloc ) in sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) in java.lang.reflect.Method.invoke (Method.java:601) in org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall Framework ( thod.java:47) in org.junit.internal.runners.model.ReflectiveCallable.run (ReflectiveCallable.java:12) in org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.java:44) in org.junit .internal.runners.statements.invokeMethod ) at org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner $ 3.run (ParentRunner.java:238) at org.junit.runners.ParentRunlener $ 1. java: 63) in org.junit.runners.ParentRunner.runChildren (ParentRunner.java:236) in org.junit.runners.ParentRunner.access $ 000 (ParentRunner.java:53) in org.junit.runners.ParentRunner $ 2.valuation (ParentRunner.java:229) at org.junit.runners.ParentRunner.run (ParentRunner.java.309) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run (JUnit4 TestReference.java:50) in org.eclipse.jdt.internal.junit.runner.TestExecution.run (TestExecution.java:38) in org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (RemoteTestRunner.java: 467) in org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (RemoteTestRunner.java:683) in org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run (RemoteTestRunner orgavaava .eclipse.jdt.internal.junit.runner.RemoteTestRunner.main (RemoteTestRunner.java:197)

+6
source share
1 answer

The problem is that your testing method does not really call NestedClass.foo() . This line:

 NestedClass.foo(); 

... actually converts to a synthetic method call that is generated in foo , for example:

 NestedClass.access$000(); 

Where access$000 as follows:

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

You can verify this using javap -c to view the actual bytecode.

At the JVM level, your outer class does not have access to foo() . The Java compiler simply synthesizes access to it, creating access$000 and calling it from your outer class whenever the source code calls foo() .

At runtime, reflection libraries do not do the same, so your mistake.

+7
source

Source: https://habr.com/ru/post/943767/


All Articles