JavaのASMでプライベートメソッドを呼び出します

user12801918:

私は、リフレクションを使用せずにプライベートメソッドを呼び出すしたいと思います:それは、ASMを使用してプライベートネイティブメソッドをフックし、それを呼び出すことが可能ですか?

ホルガー:

課題は、起動クラスを生成することはないprivateASMまたは類似のバイトコード生成ツールを介し方法。課題は、検証によって拒否されることなく、JVMにバイトコードを取得することです。

OpenJDKの/ホットスポットのために、あるsun.misc.Unsafe方法有しdefineAnonymousClass(Class<?>, byte[], Object[])、アクセサクラスを生成するランタイムクラスは、機能インタフェースを実装するようにし、呼び出しのために使用されるprivateラムダ式の本体を保持している合成方法を。

あなたは使用して、あなたのバイトコードをロードするためにこれを使用することができますprivate方法にアクセスできるように、最初の引数としてメソッドの宣言クラスを。一方、JREの独自のユースケースは、あなたも、このようなバイトコードを自分で生成する必要がないことを意味します:

MethodHandles.Lookup l = MethodHandles.privateLookupIn(Class.class, MethodHandles.lookup());
MethodHandle target = l.findSpecial(Class.class, "getDeclaredFields0",
    MethodType.methodType(Field[].class, boolean.class), Class.class);
BiFunction<Class<?>,Boolean,Field[]> a = (BiFunction)LambdaMetafactory.metafactory(
    l, "apply", MethodType.methodType(BiFunction.class), target.type().generic(),
    target, target.type().changeParameterType(1, Boolean.class))
    .getTarget().invokeExact();

その後、あなたは例えば、呼び出すことができますa.apply(Class.class, false)呼び出しますgetDeclaredFields0リフレクションなし。

privateLookupInあなたは非モジュラーコードにいるか、必要に応じ提供する場合に動作するJava 9の方法で--add-opens開くには、JVMの起動時にオプションをjava.baseあなたのモジュールに。そこリフレクションアクセスに関する警告もよく、それは右のようなアクセスは、「将来のリリースで拒否される」ことを指摘についてですされます。とにかく、どのようにJVM引数なしのJava 9で「不正な反射のアクセスを」警告非表示にするには?面白いかもしれません。

Javaの8のために、あなたはにハックする必要があるだろうLookup、適切なルックアップインスタンスを取得するクラス。この答えは解決策を示し、ここでは別のアプローチがあります。

おすすめ

転載: http://10.200.1.11:23101/article/api/json?id=478791&siteId=1