quarkusio / quarkus

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

Wrong classpath seems to be used when building native executable #38156

Open An1s9n opened 10 months ago

An1s9n commented 10 months ago

Describe the bug

Looks like Quarkus uses classpath with ALL dependencies when building a native executable: it processes dependencies needed not only by the project itself, but also dependencies of gradle plugins

Expected behavior

Native executable build is successful without exceptions

Actual behavior

Exception is thrown when building native executable:

java.lang.ClassNotFoundException: org.apache.hc.client5.http.impl.auth.NTLMEngineImpl
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageClassLoader.loadClass(NativeImageClassLoader.java:652)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
        at java.base/java.lang.Class.forName0(Native Method)
        at java.base/java.lang.Class.forName(Class.java:534)
        at java.base/java.lang.Class.forName(Class.java:513)
        at io.quarkus.runner.Feature.runtimeInitializedClasses(Unknown Source)
        at io.quarkus.runner.Feature.beforeAnalysis(Unknown Source)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.lambda$runPointsToAnalysis$9(NativeImageGenerator.java:773)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:90)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:773)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:592)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:550)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:538)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:720)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.start(NativeImageGeneratorRunner.java:142)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:97)
java.lang.NullPointerException: Cannot invoke "java.lang.Class.getTypeName()" because "aClass" is null
        at org.graalvm.nativeimage/org.graalvm.nativeimage.hosted.RuntimeClassInitialization.getUnqualifiedName(RuntimeClassInitialization.java:176)
        at org.graalvm.nativeimage/org.graalvm.nativeimage.hosted.RuntimeClassInitialization.initializeAtRunTime(RuntimeClassInitialization.java:99)
        at io.quarkus.runner.Feature.beforeAnalysis(Unknown Source)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.lambda$runPointsToAnalysis$9(NativeImageGenerator.java:773)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:90)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:773)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:592)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:550)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:538)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:720)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.start(NativeImageGeneratorRunner.java:142)
        at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:97)

How to Reproduce?

reproducer

run ./gradlew clean assemble to see the exception. Now in build.gradle.kts comment out 4d line (dependencycheck plugin) and re-run ./gradlew clean assemble, you will see a successful build without exceptions. Thе only one difference is gradle plugin which is not used in runtime, so why is dependency of this plugin is processed while building a native executable..?

Output of uname -a or ver

Darwin 192.168.1.33 23.2.0 Darwin Kernel Version 23.2.0: Wed Nov 15 21:55:06 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T6020 arm64

Output of java -version

openjdk version "17.0.7" 2023-04-18 LTS OpenJDK Runtime Environment Zulu17.42+19-CA (build 17.0.7+7-LTS) OpenJDK 64-Bit Server VM Zulu17.42+19-CA (build 17.0.7+7-LTS, mixed mode, sharing)

Mandrel or GraalVM version (if different from Java)

[1/8] Initializing... Java version: 21.0.1+12-LTS, vendor version: Mandrel-23.1.1.0-Final

Quarkus version or git rev

3.6.5

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

Gradle 8.5

Additional information

Probably HttpClientProcessor is in charge of such behavior

Also see attached output of ./gradlew buildEnvironment for dependency analysis

quarkus-bot[bot] commented 10 months ago

/cc @Karm (mandrel), @galderz (mandrel), @zakkak (mandrel,native-image)

vladimirfx commented 10 months ago

I have a similar problem.

Code generation Gradle task uses the wrong classpath which leads to random bugs in different projects when the build script classpath is changed. Adding/updating some Gradle plugins leads to a broken build OR runtime because Quarkus code generation task "sees" some classes from the Gradle plugins classpath and generates incorrect application code (which uses classes that do not exist in the application runtime classpath).

Currently, I see problems when Gradle plugins use Apache HTTP Client and Google GRPC/Protobuf libraries. But problems can arise with any "clash" of the Gradle plugin classpath and the application Quarkus extensions at any moment.

Some of our projects can't be updated to Quarkus 3.x because of this issue. Others can be broken at any moment with updates of corporate-wide Gradle conventions.

Please take a look.

zakkak commented 10 months ago

cc @glefloch @quarkusio/devtools

vladimirfx commented 9 months ago

Quarkus 2.x is EOL so we have no migration path.