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?
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.