micronaut-projects / micronaut-core

Micronaut Application Framework
http://micronaut.io
Apache License 2.0
6.08k stars 1.07k forks source link

Native image generation failing with a ClassNotFoundException: javax.inject.Provider #5655

Closed glaforge closed 3 years ago

glaforge commented 3 years ago

I created a simple application with the launcher, without any specific feature, with version 3.0.0-M2 of the framework, and added the following controller:

package mngcp;

import io.micronaut.http.annotation.*;
import io.micronaut.core.annotation.Introspected;
import java.util.List;

@Controller("/vegetable")
public class VegetableController {

    @Get(uri="/", produces="application/json")
    public List<Vegetable> index() {
        return List.of(
            new Vegetable("Potato", 80),
            new Vegetable("Tomato", 20),
            new Vegetable("Cucumber", 15),
            new Vegetable("Carrot", 42)
        );
    }
}

@Introspected
class Vegetable {
    private String name;
    private int calories;

    public Vegetable(String name, int calories) {
        this.name = name;
        this.setCalories(calories);
    }

    public int getCalories() {
        return calories;
    }

    public void setCalories(int calories) {
        this.calories = calories;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return name + " (" + calories + ")";
    }
}

When I try to build a native image within a Docker container, with `./gradlew dockerBuildNative, I get:

Fatal error:java.lang.NoClassDefFoundError
       at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
       at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
        at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:603)
        at java.base/java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1006)
        at com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:499)
        at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:370)
        at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:531)
       at com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:119)
        at com.oracle.svm.hosted.NativeImageGeneratorRunner$JDK9Plus.main(NativeImageGeneratorRunner.java:568)
Caused by: java.lang.NoClassDefFoundError: javax/inject/Provider
        at java.base/java.lang.Class.getDeclaredConstructors0(Native Method)
       at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3137)
       at java.base/java.lang.Class.getConstructor0(Class.java:3342)
        at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2553)
        at com.oracle.svm.hosted.ServiceLoaderFeature.handleType(ServiceLoaderFeature.java:316)
        at com.oracle.svm.hosted.ServiceLoaderFeature.duringAnalysis(ServiceLoaderFeature.java:178)
        at com.oracle.svm.hosted.NativeImageGenerator.lambda$runPointsToAnalysis$14(NativeImageGenerator.java:765)
        at com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:71)
       at com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:765)
        at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:582)
        at com.oracle.svm.hosted.NativeImageGenerator.lambda$run$2(NativeImageGenerator.java:495)
        at java.base/java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1407)
       at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
        at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
        at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
       at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
        at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
Caused by: java.lang.ClassNotFoundException: javax.inject.Provider
        at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
       ... 17 more
Error: Image build request failed with exit status 1

If I change to 3.0.0-M1 in gradle.properties then this time, I get:

Fatal error:java.lang.NoClassDefFoundError
       at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
        at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:603)
        at java.base/java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1006)
        at com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:499)
        at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:370)
       at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:531)
        at com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:119)
       at com.oracle.svm.hosted.NativeImageGeneratorRunner$JDK9Plus.main(NativeImageGeneratorRunner.java:568)
Caused by: java.lang.NoClassDefFoundError: jakarta/inject/Provider
        at java.base/java.lang.Class.getDeclaredConstructors0(Native Method)
        at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3137)
        at java.base/java.lang.Class.getConstructor0(Class.java:3342)
        at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2553)
        at com.oracle.svm.hosted.ServiceLoaderFeature.handleType(ServiceLoaderFeature.java:316)
        at com.oracle.svm.hosted.ServiceLoaderFeature.duringAnalysis(ServiceLoaderFeature.java:178)
        at com.oracle.svm.hosted.NativeImageGenerator.lambda$runPointsToAnalysis$14(NativeImageGenerator.java:765)
       at com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:71)
        at com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:765)
        at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:582)
       at com.oracle.svm.hosted.NativeImageGenerator.lambda$run$2(NativeImageGenerator.java:495)
       at java.base/java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1407)
       at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
        at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
        at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
       at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
        at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
Caused by: java.lang.ClassNotFoundException: jakarta.inject.Provider
        at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
        ... 17 more
Error: Image build request failed with exit status 1

> Task :dockerBuildNative FAILED

FAILURE: Build failed with an exception.

Lastly, if I change the Micronaut version to 2.5.6 in gradle.properties, I was getting:

Error: Image build request failed with exit status 137

This last error actually means that there's not enough memory in Docker Desktop. If I increase the memory to 8GB, I can build the native image successfully.

jameskleeh commented 3 years ago

This is due to a bug in GraalVM which is fixed in their master branch

glaforge commented 3 years ago

Thanks @jameskleeh for the update. I reverted to Micronaut 2.5.6 in the meantime (which worked for me). Do you have a link a GraalVM ticket about that bug?

jameskleeh commented 3 years ago

@glaforge I wish I did. When we discovered the bug it was already fixed. So I'm not sure which issue would have fixed it

graemerocher commented 3 years ago

as a workaround you can add javax.inject to your compile classpath https://search.maven.org/artifact/javax.inject/javax.inject/1/jar

ilopmar commented 3 years ago

@glaforge if you want to use Micronaut 3.0 you can download GraalVM 21.2.0-dev from https://github.com/graalvm/graalvm-ce-dev-builds/releases which contains the fix.

jameskleeh commented 3 years ago

The new version of GraalVM has fixed this issue