使用java.lang.invoke.MethodHandle调用私有方法

Mar*_*cki 8 java reflection invokedynamic java-7 methodhandle

如何使用方法句柄调用私有方法?

据我所知,只有两种可公开访问的Lookup实例:

  • MethodHandles.lookup()
  • MethodHandles.publicLookup()

并且都不允许不受限制的私人访问.

有非公众Lookup.IMPL_LOOKUP做我想做的事.是否有一些公共方法来获取它(假设SecurityManager允许它)?

Mar*_*cki 10

事实证明,使用Lookup#unreflect(方法)并暂时使方法可访问(除非在程序初始化期间完成,否则可能会引入小的安全问题).

以下是Thorben回答的修改主要方法:

public static void main(String[] args) {

    Lookup lookup = MethodHandles.lookup();
    NestedTestClass ntc = new Program().new NestedTestClass();

    try {
        // Grab method using normal reflection and make it accessible
        Method pm = NestedTestClass.class.getDeclaredMethod("gimmeTheAnswer");
        pm.setAccessible(true);

        // Now convert reflected method into method handle
        MethodHandle pmh = lookup.unreflect(pm);
        System.out.println("reflection:" + pm.invoke(ntc));

        // We can now revoke access to original method
        pm.setAccessible(false);

        // And yet the method handle still works!
        System.out.println("handle:" + pmh.invoke(ntc));

        // While reflection is now denied again (throws exception)
        System.out.println("reflection:" + pm.invoke(ntc));

    } catch (Throwable e) {
        e.printStackTrace();
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 更好的方法是使用Java SE 9中添加的MethodHandles.privateLookupIn。 (2认同)