私は、リフレクションを使用せずにプライベートメソッドを呼び出すしたいと思います:それは、ASMを使用してプライベートネイティブメソッドをフックし、それを呼び出すことが可能ですか?
課題は、起動クラスを生成することはないprivate
ASMまたは類似のバイトコード生成ツールを介し方法。課題は、検証によって拒否されることなく、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
、適切なルックアップインスタンスを取得するクラス。この答えは解決策を示し、ここでは別のアプローチがあります。