-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exceptions during static init in native build are swallowed and lead to incorrect static analysis #32298
Comments
You added a link to a Zulip discussion, please make sure the description of the issue is comprehensive and doesn't require accessing Zulip
|
Thank you for the detailed report @yrodiere
You are right, that's the root cause.
GraalVM delays error reporting in an effort to catch as many errors as possible and report them in the end. This certainly fails in this case as GraalVM fails with a
AFAIK there's no such option. This is indeed a GraalVM bug so I opened oracle/graal#6368 to track it upstream and work on a solution. I am closing this issue as this is not related to Quarkus. |
Thanks for working on this @zakkak! |
Describe the bug
In the reproducer below, a Hibernate ORM entity class is annotated with
@SQLDeleteAll
, which triggers an exception in Hibernate ORM during static init, and therefore makes the whole build fail. So far so good, that's expected behavior.What is not expected is that the exception in Hibernate ORM is nowhere to be found in the build output. Instead, GraalVM seems to try to continue the build, eventually reaches invalid conclusions about which classes are reachable at runtime or not, and ends up reporting those invalid conclusions, without ever mentioning the exception thrown during static initialization.
In the reproducer, the "reachable" class is
org.hibernate.boot.xsd.ConfigXsdSupport
(a deleted class). But this class is not reachable at runtime, and in fact you can check that very easily: if you remove the@SQLDeleteAll
annotation on the entity class in the reproducer, the native build will pass just fine.So really, GraalVM reached invalid conclusions here; maybe because static init didn't run its course.
It would be acceptable if at least the original exception was reported somewhere, but it's not :/
Expected behavior
I'd expect the log to display the stack trace of the original exception that led to the failure during static init, i.e.:
Actual behavior
I get some error about
org.hibernate.boot.xsd.ConfigXsdSupport
(a deleted class) being reachable at runtime, and nothing about the exception during static init:How to Reproduce?
Here is a reproducer adapted from the one provided by @gesker (thanks!) in #32188: https://github.com/yrodiere/orm-native-error/tree/graalvm-swallowing-exception (note this is not the default branch)
To reproduce, just check out that repository and run a native build:
It might be handy to enable static init debugging and decompilation of generated bytecode:
Note: for debugging, if you run GraalVM in a container, make sure not to rely on "fallback": you should set
-Dquarkus.native.container-build=true
explicitly. There's a bug in Quarkus with a pending PR: #32236Useful places to put a breakpoint in:
io.quarkus.hibernate.orm.runtime.PersistenceUnitsHolder#constructMetadataAdvance
: Hibernate ORM throws an exception somewhere in this methodcom.oracle.svm.hosted.classinitialization.ClassInitializationSupport#ensureClassInitialized
: GraalVM catches and "handles" the exception in these catch blocks.Output of
uname -a
orver
Linux yrodiere.redhat 6.1.7-200.fc37.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Jan 18 17:11:49 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
Output of
java -version
openjdk version "17.0.6" 2023-01-17 OpenJDK Runtime Environment Temurin-17.0.6+10 (build 17.0.6+10) OpenJDK 64-Bit Server VM Temurin-17.0.6+10 (build 17.0.6+10, mixed mode, sharing)
GraalVM version (if different from Java)
Built-in containerized version:
Quarkus version or git rev
Latest main d73bbd6
Build tool (ie. output of
mvnw --version
orgradlew --version
)Apache Maven 3.8.6 (84538c9988a25aec085021c365c560670ad80f63) Maven home: /home/yrodiere/.m2/wrapper/dists/apache-maven-3.8.6-bin/67568434/apache-maven-3.8.6 Java version: 17.0.6, vendor: Eclipse Adoptium, runtime: /home/yrodiere/tools/java/jdk-17.0.6+10 Default locale: en_US, platform encoding: UTF-8 OS name: "linux", version: "6.1.7-200.fc37.x86_64", arch: "amd64", family: "unix"
Additional information
cc @zakkak : this is the problem we discussed on Zulip
While debugging this, I ended up in this method:
https://github.com/oracle/graal/blob/202d3eb69ca980f7a93d6a7137846b340834748f/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationSupport.java#L192-L205
It reports the error and apparently marks the class that failed to initialize (here, the Quarkus application root, so
io.quarkus.runner.ApplicationImpl
, a generated class) as "to be initialized at runtime". Which is probably what causes the invalid conclusions with regard to reachable paths.That doesn't explain why the original error is never reported, though...
I wonder if there is some way to force GraalVM to stop on the first class initialization? Surely there's no point trying to run static analysis on wrong assumptions (like assuming that classes that we want to be initialized at build time will be initialized at runtime...).
The text was updated successfully, but these errors were encountered: