graal
graal copied to clipboard
[GR-51239] GraalVM native-image dynamic proxy fails to invoke methods defined in super-interfaces
Describe the issue I have a dynamic proxy on an interface, which has a super-interface that declares a default method. Invoking this default method from the sub-interface always fails.
Steps to reproduce the issue
I tried to put various entries in proxy-config.json and reflect-config.json, including what was generated by the native-image agent, but I just cannot get it to work. I tried with GraalVM 21 and 17. Any ideas what I'm doing wrong? Here's the code. I know it is a bit of a contrived example. This is the minimal version I could extract from a much more complicated code-base.
package nativetest;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
Class<?> c = TestSubInterface.class;
TestInvocationHandler<?> handler = new TestInvocationHandler<>(c);
TestSubInterface proxy = (TestSubInterface) Proxy.newProxyInstance(Main.class.getClassLoader(),
new Class<?>[] { c }, handler);
System.out.println("Result: " + proxy.doSomething());
}
public static class TestInvocationHandler<T> implements InvocationHandler {
private final Class<T> configClass;
public TestInvocationHandler(Class<T> configClass) {
this.configClass = configClass;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodHandle methodHandle = MethodHandles.lookup()
.findSpecial(configClass, method.getName(),
MethodType.methodType(method.getReturnType(), method.getParameterTypes()),
configClass);
return methodHandle.bindTo(proxy).invoke();
}
}
public interface TestInterface {
default String doSomething() {
System.out.println("Doing something");
return "Something done";
}
}
public interface TestSubInterface extends TestInterface {
}
}
While this works fine when run with java -jar
, it fails when run as native image with following error:
Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
at jdk.proxy4/jdk.proxy4.$Proxy48.doSomething(Unknown Source)
at nativetest.Main.main(Main.java:17)
at [email protected]/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH)
Caused by: java.lang.NoSuchMethodException: no such method: nativetest.Main$TestSubInterface.doSomething()String/invokeSpecial
at [email protected]/java.lang.invoke.MemberName.makeAccessException(MemberName.java:915)
at [email protected]/java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:994)
at [email protected]/java.lang.invoke.MethodHandles$Lookup.resolveOrFail(MethodHandles.java:3750)
at [email protected]/java.lang.invoke.MethodHandles$Lookup.findSpecial(MethodHandles.java:3097)
at nativetest.Main$TestInvocationHandler.invoke(Main.java:30)
... 3 more
Caused by: java.lang.NoSuchMethodError: nativetest.Main$TestSubInterface.doSomething()
at org.graalvm.nativeimage.builder/com.oracle.svm.core.methodhandles.Util_java_lang_invoke_MethodHandleNatives.resolve(Target_java_lang_invoke_MethodHandleNatives.java:335)
at [email protected]/java.lang.invoke.MethodHandleNatives.resolve(MethodHandleNatives.java:213)
at [email protected]/java.lang.invoke.MemberName$Factory.resolve(MemberName.java:962)
at [email protected]/java.lang.invoke.MemberName$Factory.resolveOrFail(MemberName.java:991)
... 6 more
Describe GraalVM and your environment:
- Both graalvm-jdk-17.0.9+11.1 and graalvm-jdk-21.0.1+12.1
- OS: Linux (tested on CentOS 7, Oracle Linux 8 and WSL2)
- Architecture: AMD64
Anyone?
Thank you for reaching out about this, we'll take a look into it shortly
Thank you for reporting this issue! This is a known problem and it is tracked with this roadmap item: https://github.com/oracle/graal/issues/7476
ETA for the fix is GraalVM for JDK 23. We will make sure to test this example while implementing the functionality.
The ability to specify methods of proxy classes in the reachability metadata was added in #8822