quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.8k stars 2.68k forks source link

Native Compilation and --link-at-build-time #30528

Closed hernael closed 1 year ago

hernael commented 1 year ago

Describe the bug

In native build process, quarkus add --link-at-build-time argument. But in my case that argument throws:

Fatal error: com.oracle.graal.pointsto.util.AnalysisError$ParsingError: Error encountered while parsing com.squareup.wire.schema.RootKt.<clinit>() 
Parsing context: <no parsing context available> 

        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.AnalysisError.parsingError(AnalysisError.java:153)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.createFlowsGraph(MethodTypeFlow.java:104)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.ensureFlowsGraphCreated(MethodTypeFlow.java:83)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.getOrCreateMethodFlowsGraph(MethodTypeFlow.java:65)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.typestate.DefaultAnalysisPolicy.staticRootMethodGraph(DefaultAnalysisPolicy.java:182)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.PointsToAnalysis.lambda$addRootMethod$0(PointsToAnalysis.java:320)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.PointsToAnalysis$2.run(PointsToAnalysis.java:507)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.executeCommand(CompletionExecutor.java:193)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.util.CompletionExecutor.lambda$executeService$0(CompletionExecutor.java:177)
        at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1395)
        at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
        at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
        at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
        at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
        at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
Caused by: org.graalvm.compiler.java.BytecodeParser$BytecodeParserError: com.oracle.graal.pointsto.constraints.UnresolvedElementException: Discovered unresolved field during parsing: okio.Options.Companion. This error is reported at image build time because class com.squareup.wire.schema.RootKt is registered for linking at image build time by command line
        at parsing com.squareup.wire.schema.RootKt.<clinit>(Root.kt:192)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.throwParserError(BytecodeParser.java:2518)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.throwParserError(SharedGraphBuilderPhase.java:110)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.iterateBytecodesForBlock(BytecodeParser.java:3393)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.handleBytecodeBlock(BytecodeParser.java:3345)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.processBlock(BytecodeParser.java:3190)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.build(BytecodeParser.java:1138)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.buildRootMethod(BytecodeParser.java:1030)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.GraphBuilderPhase$Instance.run(GraphBuilderPhase.java:97)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase.run(SharedGraphBuilderPhase.java:84)
        at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.run(Phase.java:49)
        at jdk.internal.vm.compiler/org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:446)
        at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.apply(Phase.java:42)
        at jdk.internal.vm.compiler/org.graalvm.compiler.phases.Phase.apply(Phase.java:38)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.AnalysisParsedGraph.parseBytecode(AnalysisParsedGraph.java:135)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.meta.AnalysisMethod.ensureGraphParsed(AnalysisMethod.java:685)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.parse(MethodTypeFlowBuilder.java:171)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.apply(MethodTypeFlowBuilder.java:349)
        at org.graalvm.nativeimage.pointsto/com.oracle.graal.pointsto.flow.MethodTypeFlow.createFlowsGraph(MethodTypeFlow.java:93)
        ... 13 more
Caused by: com.oracle.graal.pointsto.constraints.UnresolvedElementException: Discovered unresolved field during parsing: okio.Options.Companion. This error is reported at image build time because class com.squareup.wire.schema.RootKt is registered for linking at image build time by command line
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.reportUnresolvedElement(SharedGraphBuilderPhase.java:333)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.handleUnresolvedField(SharedGraphBuilderPhase.java:305)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.handleUnresolvedLoadField(SharedGraphBuilderPhase.java:274)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.resolveStaticFieldAccess(BytecodeParser.java:4850)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.genGetStatic(BytecodeParser.java:4776)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.genGetStatic(BytecodeParser.java:4772)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.processBytecode(BytecodeParser.java:5282)
        at jdk.internal.vm.compiler/org.graalvm.compiler.java.BytecodeParser.iterateBytecodesForBlock(BytecodeParser.java:3385)
        ... 28 more

error even stays if i add the property:

quarkus.native.additional-build-args=--initialize-at-run-time=com.squareup.wire.schema.RootKt,--allow-incomplete-classpath

the way I got it NOT to be added --link-at-build-time argument to native build phase was to add a dependency:

        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-reactive-oracle-client</artifactId>
        </dependency>

There must be a solution other than adding a dependency so that the --link-at-build-time argument is removed in native build.

Expected behavior

No response

Actual behavior

No response

How to Reproduce?

No response

Output of uname -a or ver

No response

Output of java -version

openjdk version "17.0.5"

GraalVM version (if different from Java)

mandrel-java17-22.3.0.1-Final

Quarkus version or git rev

2.16.0.CR1

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.8.6

Additional information

No response

quarkus-bot[bot] commented 1 year ago

/cc @Karm (mandrel), @galderz (mandrel), @zakkak (mandrel)

geoand commented 1 year ago

What is the exact error is you use quarkus.native.additional-build-args=--initialize-at-run-time=com.squareup.wire.schema.RootKt,--allow-incomplete-classpath?

And what is the native-image command that has been executed (it's printed in the console)?

zakkak commented 1 year ago

Related to https://github.com/quarkusio/quarkus/issues/25526

geoand commented 1 year ago

@zakkak should we close this as a duplicate?

zakkak commented 1 year ago

Yes and no :)

Yes: This is not actually a Quarkus issue. We need to write a guide about how to approach this kind of issues and point people to it.

No: https://github.com/quarkusio/quarkus/issues/25526 is a feature request for allowing users to bypass such issues, which is something we would like them to do only as a last resort. So in that sense this issue is not a duplicate per se.

In the lack of a proper guide on how to approach this I suggest we keep this open and help @hernael find a fix. Unfortunately I won't be able to help with any of these in the next couple of days, but feel free to assign this to me.

hernael commented 1 year ago

Hi @geoand @zakkak

The error mentioned in first comment is error exact that is thrown with those arguments: quarkus.native.additional-build-args=--initialize-at-run-time=com.squareup.wire.schema.RootKt,--allow-incomplete-classpath

The native command is:

/opt/mandrel/bin/native-image -J-Djava.util.logging.manager=org.jboss.logmanager.LogManager -J-Dlogging.initial-configurator.min-level=500 -J-Dsun.nio.ch.maxUpdateArraySize=100 -J-Davro.disable.unsafe=true -J-Dvertx.logger-delegate-factory-class-name=io.quarkus.vertx.core.runtime.VertxLogDelegateFactory -J-Dvertx.disableDnsResolver=true -J-Dio.netty.leakDetection.level=DISABLED -J-Dio.netty.allocator.maxOrder=3 -J-Duser.language=es -J-Duser.country=VE -J-Dfile.encoding=UTF-8 --features=io.quarkus.caffeine.runtime.graal.CacheConstructorsFeature,io.quarkus.runner.Feature,io.quarkus.runtime.graal.ResourcesFeature,io.quarkus.runtime.graal.DisableLoggingFeature -J--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED -J--add-opens=java.base/java.text=ALL-UNNAMED -J--add-opens=java.base/java.io=ALL-UNNAMED -J--add-opens=java.base/java.lang.invoke=ALL-UNNAMED -J--add-opens=java.base/java.util=ALL-UNNAMED -H:+CollectImageBuildStatistics -H:ImageBuildStatisticsFile=process-transaction-application-2.1-SNAPSHOT-runner-timing-stats.json -H:BuildOutputJSONFile=process-transaction-application-2.1-SNAPSHOT-runner-build-output-stats.json -H:ReflectionConfigurationFiles=reflection-kafka-proto-config.json --initialize-at-run-time=com.squareup.wire.schema.RootKt --allow-incomplete-classpath -H:+AllowFoldMethods -J-Djava.awt.headless=true --no-fallback --link-at-build-time -H:+ReportExceptionStackTraces -H:-AddAllCharsets --enable-url-protocols=http,https -H:NativeLinkerOption=-no-pie -H:-UseServiceLoaderFeature -H:+StackTrace -H:AdditionalSecurityProviders=com.sun.security.sasl.Provider,org.apache.kafka.common.security.oauthbearer.internals.OAuthBearerSaslClientProvider,org.apache.kafka.common.security.scram.internals.ScramSaslClientProvider -J--add-exports=org.graalvm.sdk/org.graalvm.nativeimage.impl=ALL-UNNAMED -J--add-exports=org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk=ALL-UNNAMED --exclude-config io\.netty\.netty-codec /META-INF/native-image/io\.netty/netty-codec/generated/handlers/reflect-config\.json --exclude-config io\.netty\.netty-handler /META-INF/native-image/io\.netty/netty-handler/generated/handlers/reflect-config\.json process-transaction-application-2.1-SNAPSHOT-runner -jar process-transaction-application-2.1-SNAPSHOT-runner.jar

Important note, before updating there were no errors! and I used:

quarkus.platform.version: 2.13.2.Final graal.version: mandrel-java17-21.3.1.1-Final

I just made a change of quarkus and native compiler. Maybe the problem is mandrel

galderz commented 1 year ago

I don't know how 21.3 would work, but if I were you, I would look to your application, its dependencies and see why the jar containing okio.Options.Companion might not be included in the list of jars that native image takes as input. I'm neither a Kotlin or Gradle expert.

No idea where you got the clue to add the quarkus-reactive-oracle-client dependency but if that works, that's likely due to extension behind it, or the oracle client jar itself, which under the covers sets the allow incomplete classpath underneath. In any case, going down this path is not recommended.

A preferred approach might be to pass in --initialize-at-run-time=com.squareup or a problematic package that is underneath that within the additional build arguments.

hernael commented 1 year ago

@galderz for some unknown reason, when i add the oracle dependency (quarkus-reactive-oracle-client), quarkus doesn't add --link-at-build-time argument in native-image command. With that argument Mandrel ignores --initialize-at-run-time=com.squareup.wire.schema.RootKt and throws exception, but if --link-at-build-time argument is removed everything compiles fine.

It's like --link-at-build-time has higher priority than --initialize-at-run-time=com.squareup.wire.schema.RootKt in Mandrel

Change --initialize-at-run-time=com.squareup.wire.schema.RootKt for --initialize-at-run-time=com.squareup makes no difference, error still occurs.

zakkak commented 1 year ago

@hernael can you please have a look at https://github.com/quarkusio/quarkus/pull/30716 and see if the information there are enough for you to overcome the issue? If not please provide feedback on how to improve it.

turing85 commented 1 year ago

@zakkak I have a very similar issue (details are in zulip). In my case, a constructor is not found. I have verified that the class is on the classpath (mvn dependency:tree shows the dependency that contains the class, is present). And I am also quite sure that there are no optional dependencies involved. Any hints on how to tackle this situation?

galderz commented 1 year ago

@turing85 Native reports.

zakkak commented 1 year ago

@turing85 you might be hitting the issue I describe in https://github.com/oracle/graal/pull/4661, i.e., the error you are seeing might be missleading and the actual issue is different.

jerboaa commented 1 year ago

quarkus.platform.version: 2.13.2.Final graal.version: mandrel-java17-21.3.1.1-Final

Hmm, so you are using Quarkus 2.13.x with 21.3 Mandrel? For 2.13 Quarkus it's recommended to use 22.3 mandrel. Have you tried that?

Edit: The original report mentions 22.3 GraalVM/Mandrel. It would be good to know which it is :)

zakkak commented 1 year ago

Hmm, so you are using Quarkus 2.13.x with 21.3 Mandrel? For 2.13 Quarkus it's recommended to use 22.3 mandrel.

Just a clarification for the record.

For Quarkus 2.13.0 -- 2.13.3 it's actually recommended to use GraalVM/Mandrel 21.3 or 22.2. For 2.13.4 onwards, it's recommended to use 22.3. See https://github.com/graalvm/mandrel/wiki.

That being said, it's always recommended to use the latest release. Both 2.13.2 and 21.3 are outdated at this point, so please consider updating to Quarkus 2.13.7 or later and GraalVM/Mandrle 22.3 regardless of this issue.

zakkak commented 1 year ago

@hernael is this still an issue for you?

luis-rabock commented 1 year ago

I have the same issue:

com.pengrad.telegrambot.impl.TelegramBotClient is registered for linking at image build time by command line

Running: mvn package -Dquarkus.package.type=native -Dquarkus.native.additional-build-args="--initialize-at-run-time=com.pengrad.telegrambot.impl.TelegramBotClient, --allow-incomplete-classpath"

GraalVm: 22.3.r19-grl quarkus: 3.0.0.Alpha4

hernael commented 1 year ago

Hi @zakkak yes, if there is already a quarkus property so that --link-at-build-time argument is not added in native compile no, if there is no way to remove that option

zakkak commented 1 year ago

@hernael and @luis-rabock did you try following the short guide in https://quarkus.io/version/main/guides/native-reference#i-get-a-analysiserrorparsingerror-when-building-a-native-executable-due-to-an-unresolvedelementexception-what-can-i-do ?

If not, please do. If yes, please let me know what you tried and why it doesn't work so that we can improve that guide.

Thanks

galderz commented 1 year ago

@luis-rabock Please open a different issue to avoid creating confusion.

@hernael Please follow @zakkak's advice. Also, you still didn't provide the error(s) you get when you pass in --initialize-at-run-time=com.squareup.wire.schema.RootKt or --initialize-at-run-time=com.squareup. Sure, adding those flags might still cause errors but they should be slightly different and this is important for us to be able to help further. Or provide a reproducer for us to run.

hernael commented 1 year ago

@zakkak and @galderz adding --initialize-at-run-time=com.squareup.wire.schema.RootKt argument is required, otherwise my application fails to compile natively indicating that it must be added. The problem is that when --link-at-build-time argument is added then native compiler ignores the other argument and fails with same error as if the first argument had not been passed.

My application only works if --initialize-at-run-time=com.squareup.wire.schema.RootKt argument is added and --link-at-build-time is not added.

The problem is that currently quarkus almost always adds --link-at-build-time argument, and the only way I found to stop it from adding it is to add the dependency on: quarkus-reactive-oracle-client

zakkak commented 1 year ago

@hernael Can you please let us know if you tried following the guide I mention in https://github.com/quarkusio/quarkus/issues/30528#issuecomment-1419694995 and https://github.com/quarkusio/quarkus/issues/30528#issuecomment-1465940645?

For further help (if the guide doesn't help you resolve the issue) we will also need a reproducer (i.e. a maven/gradle project reproducing the error).

galderz commented 1 year ago

@zakkak and @galderz adding --initialize-at-run-time=com.squareup.wire.schema.RootKt argument is required, otherwise my application fails to compile natively indicating that it must be added. The problem is that when --link-at-build-time argument is added then native compiler ignores the other argument and fails with same error as if the first argument had not been passed.

My application only works if --initialize-at-run-time=com.squareup.wire.schema.RootKt argument is added and --link-at-build-time is not added.

^ That sounds odd. By default GraalVM initializes classes at runtime unless you specify which classes to initialize at build time. What --link-at-build-time does is change the default so that all classes are initialized at build time and only those specified otherwise are initialized at runtime. Hence, if --link-at-build-time is not added, there would be no need to add any --initialize-at-run-time for that class, unless there's some other thing at play here.

The problem is that currently quarkus almost always adds --link-at-build-time argument, and the only way I found to stop it from adding it is to add the dependency on: quarkus-reactive-oracle-client

That is not a "problem". It's designed that way. So far all the issues we are aware about build time initialized classes can be solved by marking the necessary classes to be initialized at runtime. To reiterate @zakkak said, we can't help further without a reproducer or some more tangible information from you (see previous comments).

galderz commented 1 year ago

One more thing you can try if you're feeling adventurous: download a GraalVM 23.0 snapshot and run with -H:+UseNewExperimentalClassInitialization and see if your odd case is solved that way alternatively (see details).

zakkak commented 1 year ago

^ That sounds odd. By default GraalVM initializes classes at runtime unless you specify which classes to initialize at build time. What --link-at-build-time does is change the default so that all classes are initialized at build time and only those specified otherwise are initialized at runtime. Hence, if --link-at-build-time is not added, there would be no need to add any --initialize-at-run-time for that class, unless there's some other thing at play here.

@galderz that's not true.

The build time initialization is done in https://github.com/quarkusio/quarkus/blob/d08d31fa598cbad2a2b275cd313e707b4d1acab2/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageFeatureStep.java#L98-L99

--link-at-build-time is not related to build-time initialization. --link-at-build-time essentially instructs GraalVM/Mandrel to fail if a reachable (according to the static analysis) class is not available on the classpath at build time (regardless if the said class is run-time or build-time initialized).

To my understanding this issue is not a run-time vs build-time initialization issue, but an incomplete classpath initialization issue. https://quarkus.io/version/main/guides/native-reference#i-get-a-analysiserrorparsingerror-when-building-a-native-executable-due-to-an-unresolvedelementexception-what-can-i-do is meant to help developers address such issues.

galderz commented 1 year ago

Ah yes, thx for correcting me @zakkak :)

galderz commented 1 year ago

@hernael Have you checked where the jar that contains okio.Options.Companion is and what kind of dependency com.squareup.wire.schema.RootKt has on it? Even if the class is not really used by your application, adding the jar that contains the okio.Options.Companion version that com.squareup.wire.schema.RootKt expects to the classpath should work.

geoand commented 1 year ago

Closing for lack of feedback

floka94 commented 1 year ago

@galderz @geoand Still have the same error when using:

        <dependency>
            <groupId>org.telegram</groupId>
            <artifactId>telegrambots</artifactId>
            <version>6.7.0</version>
        </dependency>

Error:

Caused by: com.oracle.graal.pointsto.constraints.UnresolvedElementException: Discovered unresolved type during parsing: javax.ws.rs.core.Context. This error is reported at image build time 
because class org.glassfish.jersey.inject.hk2.ContextInjectionResolverImpl is registered for linking at image build time by command line

I tried to set --initialize-at-run-time in application.properties but no success.

quarkus.native.additional-build-args=--initialize-at-run-time=org.glassfish.jersey.inject.hk2.ContextInjectionResolverImpl

galderz commented 1 year ago

One more thing you can try if you're feeling adventurous: download a GraalVM 23.0 snapshot and run with -H:+UseNewExperimentalClassInitialization and see if your odd case is solved that way alternatively (see details).

@floka94 ^

galderz commented 1 year ago

Actually, the new class initialization method is on by default on master graal master since today. You can wait a few days, download a nightly build from here and you don't have to pass any new parameters to try the new class initialization mechanism.

floka94 commented 1 year ago

Thx, i will try!