Just spotted a Quarkus/Graal master issue, see (https://github.com/quarkusio/quarkus/issues/7422):
$ mvn clean install -Dnative -pl integration-tests/optaplanner-jackson
...
Error: com.oracle.svm.hosted.substitute.DeletedElementException: Unsupported type jdk.internal.reflect.MethodAccessorGenerator is reachable
To diagnose the issue, you can add the option --report-unsupported-elements-at-runtime. The unsupported element is then reported at run time when it is accessed the first time.
Detailed message:
Trace:
at parsing jdk.internal.reflect.ReflectionFactory.generateConstructor(ReflectionFactory.java:513)
Call path from entry point to jdk.internal.reflect.ReflectionFactory.generateConstructor(Class, Constructor):
at jdk.internal.reflect.ReflectionFactory.generateConstructor(ReflectionFactory.java:513)
at jdk.internal.reflect.ReflectionFactory.newConstructorForSerialization(ReflectionFactory.java:506)
at java.io.ObjectStreamClass.getSerializableConstructor(ObjectStreamClass.java:1516)
at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:509)
at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:484)
at com.oracle.svm.core.jdk.Target_java_security_AccessController.doPrivileged(SecuritySubstitutions.java:81)
at sun.security.pkcs11.SunPKCS11.initToken(SunPKCS11.java:1028)
at sun.security.pkcs11.SunPKCS11$TokenPoller.run(SunPKCS11.java:852)
at java.lang.Thread.run(Thread.java:834)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:517)
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:193)
at com.oracle.svm.core.code.IsolateEnterStub.PosixJavaThreads_pthreadStartRoutine_e1f4a8c0039f8337338252cd8734f63a79b5e3df(generated:0)
I suspect this is caused by the following change https://github.com/oracle/graal/commit/eab7e93b585febf7c2c68948af70157732767963
The call path above is not under Quarkus control, so I'd assume this is a regression on svm?
Testing a substitution to get ReflectionFactory.generateConstructor() to return null...
PR sent #2194
@galderz I think the problem already starts at sun.security.pkcs11.SunPKCS11$TokenPoller.run. Its potential execution at image runtime ultimately drags in MethodAccessorGenerator which does bytecode generation and dynamic class loading. If that code would get executed at image runtime it would fail. If we cut the problem at the root (i.e. TokenPoller.run we can avoid having lots of code in an image that wouldn't work at image runtime anyway. I will provide a PR that deals with SunPKCS11$TokenPoller.run. cc @christianwimmer
@galderz thanks for the pointers. It looks like we have a general problem with allowing serialization specific code to wander off into stuff that we cannot support.
The underlying issue is probably not related to SunPKCS11. It is an unfortunate side effect of the static analysis that everything below a AccessController.doPrivileged call is more or less random. Since the analysis is not context sensitive, every call to doPrivileged has a call edge to every action, and our printing of the shortest call path leads to a stack trace that cannot happen at run time.
I'm trying to come up with an earlier cut-off of serialization code so that we get the true call path that causes the problem.
My idea is to add the following code to disallow serialization:
@Delete("Object serialization is currently not supported")
@TargetClass(java.io.ObjectStreamClass.class)
final class Target_java_io_ObjectStreamClass {
}
Adding just that fails our gates, so I have to investigate further. But it might still help you, so you can give it a try if you want.
@christianwimmer Tried your suggestion but didn't work, we've got failures early on (e.g. here).
@galderz Thanks, I'm always amazed how bad Java code can be: https://github.com/google/gson/blob/4d735f190336ddf241eee48fa8495eabf637a330/gson/src/main/java/com/google/gson/internal/UnsafeAllocator.java#L62
@galderz Here is a less restrictive code to prevent usage of ObjectStreamClass. It deletes the methods that produce or return an instance, so I hope it is sufficient to narrow down your problem. But since it does not prevent usage of ObjectStreamClass itself it should not fail in the gson use case.
@TargetClass(java.io.ObjectStreamClass.class)
@SuppressWarnings({"unused"})
final class Target_java_io_ObjectStreamClass {
@Delete("Object serialization is currently not supported")
private static native ObjectStreamClass lookup(Class<?> cl, boolean all);
@Delete("Object serialization is currently not supported")
private Target_java_io_ObjectStreamClass(final Class<?> cl) {
}
@Delete("Object serialization is currently not supported")
private Target_java_io_ObjectStreamClass() {
}
}
@christianwimmer Apologies for the delay, testing your suggestion.
This doesn't yet work for us (see here). I'm checking with the other Quarkus devs to see where these xstream dependency is coming from and its use.
Btw @christianwimmer, your latest suggestion would still make the original reported error appear eventually since you're forbidding paths to ObjectStreamClass(Class) constructor, wouldn't it?
Oh,I think this is only to diagnose the real root path to lookup... right?
Most helpful comment
@galderz Thanks, I'm always amazed how bad Java code can be: https://github.com/google/gson/blob/4d735f190336ddf241eee48fa8495eabf637a330/gson/src/main/java/com/google/gson/internal/UnsafeAllocator.java#L62