reactor / reactor-core

Non-Blocking Reactive Foundation for the JVM
http://projectreactor.io
Apache License 2.0
4.98k stars 1.21k forks source link

Native Image UnresolvedElementException sun.misc.SharedSecrets since version 3.5.2 #3334

Closed JohT closed 1 year ago

JohT commented 1 year ago

While updating io.projectreactor reactor-core from version 3.5.1 to 3.5.2, the following error occurs in my showcase-quarkus-eventsourcing GraalVM native image build (Java 17):

Caused by: com.oracle.graal.pointsto.constraints.UnresolvedElementException: Discovered unresolved type during parsing: sun.misc.SharedSecrets. This error is reported at image build time because class reactor.core.publisher.Traces$SharedSecretsCallSiteSupplierFactory$TracingException is registered for linking at image build time by command line
[493](https://github.com/JohT/showcase-quarkus-eventsourcing/actions/runs/3899597517/jobs/6659395744#step:6:494)
    at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.reportUnresolvedElement(SharedGraphBuilderPhase.java:333)

References:

Expected Behavior

Succeeding native image build for Java 17 that isn't influenced by features that aren't used.

Actual Behavior

Native image build fails because of missing sun.misc.SharedSecrets that weren't needed prior to version 3.5.2. I suspect the newly added reflect-config.json, but am not sure why this is the case.

Steps to Reproduce

See Failed Build Log. Or checkout showcase-quarkus-eventsourcing branch renovate/patch-reactor-core.version and follow the instructions to build the native image.

Possible Solution

I tried to change my reflection-config.json and the --exclude-config. Both didn't work. I'll continue trying.

Would it be possible to find an alternative to the use of sun.misc.SharedSecrets? Or is there a configuration or a dependency that can be added by users of this library to get it to work with Java 17?

Your Environment

violetagg commented 1 year ago

@JohT I created one simple application that uses only reactor-core and I do not observe any issues with this application. https://github.com/violetagg/GH-3334

JohT commented 1 year ago

@violetagg, I'll have a look at it when I find some time and try "to break" it to ideally get a simple reproducer.

JohT commented 1 year ago

@violetagg, i could reproduce the issue after some experimentation by adding the native image build argument --link-at-build-time. This seems to get activated by default when using Quarkus. Maybe this is also related to the discussion in the Quarkus Issue 25526: Add property to disable link-at-build-time

I needed to add slf4j-api to overcome an error that classes of this library are missing.

References:

violetagg commented 1 year ago

@JohT So basically you are disabling the default behaviour in GraalVM which is --allow-incomplete-classpath https://github.com/oracle/graal/pull/4305

Before this PR, support for an incomplete class path must be enabled by manually via 
--allow-incomplete-classpath. This ensures that no linking errors are thrown at run time. 
But since in practice many large projects needs to specify this option 
because optional dependencies are not always on the class path. 
So it is necessary to flip the default and enable the support by default.

I would recommend to follow up with Quarkus maintainers as it seems other people also experience the same problem. Also it seems that there is some solution applied for Oracle JDBC https://github.com/quarkusio/quarkus/pull/24213#issuecomment-1063881126

JohT commented 1 year ago

From https://www.graalvm.org/22.1/reference-manual/native-image/BuildConfiguration/#specifying-types-required-to-be-defined-at-build-time:

A well-structured library or application should handle linking of Java types (ensuring all reachable Java types are fully defined at build time) when building a native executable by itself. The default behavior is to throw linking errors, if they occur, at run time. However, you can prevent unwanted linking errors by specifing which classes are required to be fully linked at build time. For that, use the --link-at-build-time option.

As i understand this, --link-at-build-time is actually a good thing that follows the fail fast principle by communicating errors at build time to prevent them to happen during runtime. Or in other words, if --link-at-build-time is recommended then it should work in my opinion.

What I still don't get is why this error occurs in version 3.5.2 after providing the reflection-config.json with Related reactor-core commit. If the reproducer is switched to version 3.5.1 then everything seems fine.

JohT commented 1 year ago

@violetagg, is there a chance to have a look at https://github.com/reactor/reactor-core/blob/main/reactor-core/src/main/java/reactor/core/publisher/Traces.java and simplify the code to not use sun.misc.SharedSecrets and still work with Java 8? This would also lead to a simplified build in https://github.com/reactor/reactor-core/blob/912441f7d36adfb84f06595cecd8895b7518d8c9/reactor-core/build.gradle#L308

violetagg commented 1 year ago

@JohT Please check this PR #3339

JohT commented 1 year ago

Thank you very much. 👍 Version 3.5.3 works on my side.