Средство поиска MethodHandle

насколько JavaDoc состояния MethodHandles.lookup() возвращает объект, который имеет возможность доступа к тому же методу / функциям / конструктору, что и вызывающий эту функцию. В частности, если вызывающий может получить доступ к некоторым частным данным, так как этот MethodHandles.Поиск объекта. Код ниже демонстрирует, что это false. Где я ошибаюсь?

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:

вот что я получил:

java.ленг.IllegalAccessException: участник является частным: MethodHandlerAccessTest$NestedClass.foo () пустота, от MethodHandlerAccessTest at Ява.ленг.взывать.MemberName.makeAccessException (MemberName.java: 507) на Ява.ленг.взывать.MethodHandles$Lookup.checkAccess (MethodHandles.java: 1182) на Ява.ленг.взывать.MethodHandles$Lookup.checkMethod (MethodHandles.java: 1162) на Ява.ленг.взывать.MethodHandles$Lookup.accessStatic (MethodHandles.java: 591) на Ява.ленг.взывать.MethodHandles$Lookup.findStatic (MethodHandles.java: 587) на MethodHandlerAccessTest.testPrivateAccess (MethodHandlerAccessTest.java: 19) в Sun.отражать.NativeMethodAccessorImpl.invoke0 (собственный метод) at солнце.отражать.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java: 57) на солнце.отражать.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java: 43) на Яве.ленг.отражать.Метод.метод Invoke.java: 601) at орг.тесты JUnit.бегуны.модель.FrameworkMethod$1.runReflectiveCall (FrameworkMethod.java: 47) на орг.тесты JUnit.внутренний.бегуны.модель.ReflectiveCallable.run (ReflectiveCallable.java: 12) на орг.тесты JUnit.бегуны.модель.FrameworkMethod.invokeExplosively (FrameworkMethod.java: 44) на орг.тесты JUnit.внутренний.бегуны.заявления.Призыв.оценить (InvokeMethod.java: 17) в орг.тесты JUnit.бегуны.ParentRunner.ранлиф (ParentRunner.java: 271) at орг.тесты JUnit.бегуны.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java: 70) на орг.тесты JUnit.бегуны.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java: 50) в орг.тесты JUnit.бегуны.ParentRunner$3.run (ParentRunner.java: 238) at орг.тесты JUnit.бегуны.ParentRunner$1.расписание (ParentRunner.Ява:63) в орг.тесты JUnit.бегуны.ParentRunner.runChildren (ParentRunner.java: 236) at орг.тесты JUnit.бегуны.ParentRunner.доступ к $ 000 (ParentRunner.java: 53) at орг.тесты JUnit.бегуны.ParentRunner$2.оценка (ParentRunner.java: 229) at орг.тесты JUnit.бегуны.ParentRunner.run (ParentRunner.java: 309) at орг.затмение.JDT, предназначенным.внутренний.junit4.бегун.JUnit4TestReference.run (JUnit4TestReference.java: 50) на орг.затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.Тестексекция.run (TestExecution.java: 38) на орг.затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.RemoteTestRunner.runTests (RemoteTestRunner.java: 467) на орг.затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.RemoteTestRunner.runTests (RemoteTestRunner.java: 683) на орг.затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.RemoteTestRunner.run (RemoteTestRunner.java: 390) на орг.затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.RemoteTestRunner.main (RemoteTestRunner.java: 197)

1 ответов


проблема в том, что ваш метод испытаний не действительно вызов NestedClass.foo(). Эта строка:

NestedClass.foo();

... фактически преобразуется в вызов синтетический метод, который генерируется в foo, например:

NestedClass.access0();

здесь access0 выглядит так:

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

вы можете проверить это с помощью javap -c чтобы посмотреть на фактический байт-код.

на уровне JVM, ваш внешний класс не имеет доступа к foo(). Компилятор Java просто синтезирует доступ к нему путем создания access0 и вызывая его из внешнего класса, когда исходный код вызывает foo().

во время выполнения, библиотеки отражения не сделайте то же самое, следовательно, ваша ошибка.