So weit wie JavaDoc-Status MethodHandles.lookup()
Funktionen zurückgibt, die Zugriff auf die gleiche Methode/Funktionen/Konstruktor wie der Aufrufer dieser Funktion haben. Insbesondere, wenn der Aufrufer auf einige private Daten zugreifen kann, beispielsweise diese MethodHandles.Lookup-Funktion. Der folgende Code zeigt, dass dies falsch ist. Wo ich falsch liege?MethodHandle Lookup-Einrichtung
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:
Dies ist, was ich bekommen:
java.lang.IllegalAccessException: Mitglied ist privat: MethodHandlerAccessTest $ NestedClass.foo() void, von MethodHandlerAccessTest unter java.lang.invoke.MemberName.makeAccessException (MemberName.java:507) um java.lang.invoke.MethodHandles $ L ookup.checkAccess (MethodHandles.java:1182) bei java.lang.invoke.MethodHandles $ Lookup.checkMethod (MethodHandles.java:1162) bei java.lang.invoke.MethodHandles $ Lookup.accessStatic (MethodHandles.java: 591) bei java.lang.invoke.MethodHandles $ Lookup.findStatic (MethodHandles.java:587) bei MethodHandlerAccessTest.testPrivateAccess (MethodHandlerAccessTest.java:19) bei sun.reflect.NativeMethodAccessorImpl.invoke0 (Mutter Methode) bei sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:57) bei sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke (Methode.java:601) um org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall (FrameworkMethod.java:47) um org.junit.internal.runners. model.ReflectiveCallable.run (ReflectiveCallable.java:12) bei org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.java:44) bei org.junit.internal.runners.statements.InvokeMethod.evaluate (InvokeMethod.java:17) bei org.junit.runners.ParentRunner.runLeaf (ParentRunner.java:271) bei org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:70) bei org.junit.runners .BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:50) bei org.junit.runners.ParentRunner $ 3.run (ParentRunner.java:238) um org.junit.runners.ParentRunner $ 1.schedule (ParentRunner.java:63) um org.junit.runners.ParentRunner.runChildren (ParentRunner.java:236) um org.junit.runners.ParentRunner.access $ 000 (ParentRunner.java:53) um org.junit.runners.ParentRunner $ 2.evaluate (ParentRunner.java:229) um org.junit. runners.ParentRunner.run (ParentRunner.java:309) bei org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run (JUnit4TestReference.java:50) bei org.eclipse.jdt.internal.junit.runner .TestExecution.run (TestExecution.java:38) um org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (Remo teTestRunner.java:467) bei org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (RemoteTestRunner.java:683) bei org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run (RemoteTestRunner.java:390) unter org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main (RemoteTestRunner.java: 197)
Vielen Dank für Ihre Erklärung. Ich habe anderswo von * synthetischen Feldern/Methoden * gehört, aber ich habe nie wirklich mit ihm gesprochen. Warum hat MethodHandle dieses Verhalten nicht simuliert? Aus dem JavaDoc der Methode lookup() 'Gibt ein Suchobjekt auf dem Aufrufer zurück, das auf alle Methodenhandles zugreifen kann, auf die der Aufrufer Zugriff hat, einschließlich direkte Methodenhandles für private Felder und Methoden. Dieses Nachschlageobjekt ist eine Funktion, die an vertrauenswürdige Agenten delegiert werden kann. Ich habe es erwartet. – alexsmail
@alexsmail: Der Compiler kann die synthetische Methode wie gewünscht implementieren. Ich möchte nicht, dass die JRE versucht, dasselbe zu tun. Es ist wichtig zu unterscheiden, was die * Sprache * erlaubt und was der * Bytecode * erlaubt. Was die VM betrifft, rufen Sie nicht 'foo()' auf, und Sie haben keinen Zugriff darauf. Die Sprache ist in der Lage, Ihnen "spezielle" Rechte zu geben, indem Sie die zusätzliche Methode hinzufügen und diese aufrufen - aber das ist nur ein Sprachproblem. Der Aufrufer (die äußere Klasse) hat wirklich * keinen Zugriff auf 'foo()' aus der Perspektive der VM. –