13

メソッド ハンドルを使用してプライベート メソッドを呼び出すにはどうすればよいですか?

私が見る限り、公的にアクセス可能なLookupインスタンスは 2 種類しかありません。

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

また、無制限のプライベート アクセスも許可しません。

Lookup.IMPL_LOOKUP私がやりたいことをしている非公開があります。それを取得する公的な方法はありますか (SecurityManager が許可していると仮定して) ?

4

3 に答える 3

3

これがあなたが本当に望んでいるものかどうかはわかりません。おそらく、それで達成したいことについて、もう少し情報を提供できます。しかし、 にアクセスしたい場合はLookup.IMPL_LOOKUP、次のコード サンプルのように実行できます。

public class Main {

public static void main(String[] args) {

    Lookup myLookup = MethodHandles.lookup(); // the Lookup which should be trusted
    NestedTestClass ntc = new Main().new NestedTestClass(); // test class instance

    try {
        Field impl_lookup = Lookup.class.getDeclaredField("IMPL_LOOKUP"); // get the required field via reflections
        impl_lookup.setAccessible(true); // set it accessible
        Lookup lutrusted = (Lookup) impl_lookup.get(myLookup); // get the value of IMPL_LOOKUP from the Lookup instance and save it in a new Lookup object

        // test the trusted Lookup
        MethodHandle pmh = lutrusted.findVirtual(NestedTestClass.class, "gimmeTheAnswer", MethodType.methodType(int.class));
        System.out.println(pmh.invoke(ntc));

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

}

// nested class with private method for testing
class NestedTestClass{

    @SuppressWarnings("unused")
    private int gimmeTheAnswer(){

        return 42;
    }
}

}

JDK 7 で動作しますが、JDK 8 では壊れる可能性があります。注意してください! アンチウイルスを実行すると、アラームが発生しました。それを行うための公開またはクリーンな方法はないと思います。

私は同様の問題を抱えていましたが、最終的に解決策を見つけました: Access non-public (java-native) classes from JDK (7)

于 2013-10-03T11:31:05.513 に答える
-2

これは、プライベート関数に引数を含む同様のソリューションです(たまたま、以前のプロジェクトのコードが横たわっていました):

クラス名: InspectionTree.java

関数シグネチャ: private String getSamePackagePathAndName(String className, String classPath)

String firstName = "John";
String lastName = "Smith";

//call the class's constructor to set up the instance, before calling the private function
InspectionTree inspectionTree = new InspectionTree(firstName, lastName);

String privateMethodName ="getSamePackagePathAndName";        
Class[] privateMethodArgClasses = new Class[] { String.class, String.class };

Method method = 
         inspectionTree.getClass().getDeclaredMethod(privateMethodName, privateArgClasses);

method.setAccessible(true);

String className = "Person";
String classPath = "C:\\workspace";

Object[] params = new Object[]{className, classPath};        

//note the return type of function 'getSamePackagePathAndName' is a String, so we cast
//the return type here as a string
String answer=  (String)method.invoke(inspectionTree, params);

method.setAccessible(false);
于 2013-10-02T12:30:46.950 に答える