Reputation:
I would like to invoke a private method without using Reflection: is it possible to hook a private native method by using ASM and invoke it?
Upvotes: 2
Views: 748
Reputation: 298123
The challenge is not to generate a class invoking the private
method via ASM or a similar bytecode generation tool. The challenge is to get the bytecode into the JVM without being rejected by the verifier.
For OpenJDK/HotSpot, there is sun.misc.Unsafe
which has the method defineAnonymousClass(Class<?>, byte[], Object[])
which is used for generating accessor classes, like the runtime classes implementing functional interfaces and invoking the private
synthetic methods holding a lambda expression’s body.
You could use this to load your bytecode, using the private
method’s declaring class as first argument, to make the method accessible. On the other hand, the JRE’s own use case implies that you don’t even need to generate such bytecode yourself:
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();
Then, you can call, e.g. a.apply(Class.class, false)
which will invoke getDeclaredFields0
without Reflection.
privateLookupIn
is a Java 9 method which will work if you’re in non-modular code or provide the necessary --add-opens
option at JVM startup, to open java.base
to your module. There will be a warning about the Reflection access and well, it is right about noting that such access “will be denied in a future release”. Anyway, How to hide warning "Illegal reflective access" in java 9 without JVM argument? might be interesting.
For Java 8, you’d need to hack into the Lookup
class to get an appropriate lookup instance. This answer shows a solution, here is another approach.
Upvotes: 2