When using @DataJpaTest in a native image, the build aborts with:
Error: Classes that should be initialized at run time got initialized during image building:
------------------------------------------------------------------------------------------------------------------------
org.springframework.boot.jdbc.EmbeddedDatabaseConnection was unintentionally initialized at build time. To see why org.springframework.boot.jdbc.EmbeddedDatabaseConnection got initialized use --trace-class-initialization=org.springframework.boot.jdbc.EmbeddedDatabaseConnection
To see how the classes got initialized, use --trace-class-initialization=org.springframework.boot.jdbc.EmbeddedDatabaseConnection
See the reproducer here.
Comment From: mhalbritter
The same happens with @DataJdbcTest, as seen here.
Comment From: mhalbritter
And with @JdbcTest, as seen here.
Comment From: mhalbritter
I ran it with trace class initialization, and got this:
Error: Classes that should be initialized at run time got initialized during image building:
org.springframework.boot.jdbc.EmbeddedDatabaseConnection was unintentionally initialized at build time. org.springframework.boot.jdbc.EmbeddedDatabaseConnection caused initialization of this class with the following trace:
at org.springframework.boot.jdbc.EmbeddedDatabaseConnection.<clinit>(EmbeddedDatabaseConnection.java:50)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Unknown Source)
at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:568)
at java.lang.Class.getEnumConstantsShared(Class.java:3837)
at java.lang.Class.enumConstantDirectory(Class.java:3859)
at java.lang.Enum.valueOf(Enum.java:267)
at sun.reflect.annotation.AnnotationParser.parseEnumValue(AnnotationParser.java:479)
at sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:344)
at java.lang.reflect.Method.getDefaultValue(Method.java:717)
at sun.reflect.annotation.AnnotationType.<init>(AnnotationType.java:133)
at sun.reflect.annotation.AnnotationType.getInstance(AnnotationType.java:85)
at sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:262)
at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:121)
at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:73)
at java.lang.Class.createAnnotationData(Class.java:4068)
at java.lang.Class.annotationData(Class.java:4057)
at java.lang.Class.getDeclaredAnnotation(Class.java:3996)
at org.junit.platform.commons.util.AnnotationUtils.findAnnotation(AnnotationUtils.java:150)
at org.junit.platform.commons.util.AnnotationUtils.findMetaAnnotation(AnnotationUtils.java:198)
at org.junit.platform.commons.util.AnnotationUtils.findAnnotation(AnnotationUtils.java:156)
at org.junit.platform.commons.util.AnnotationUtils.findAnnotation(AnnotationUtils.java:137)
at org.junit.jupiter.engine.descriptor.DisplayNameUtils.determineDisplayName(DisplayNameUtils.java:73)
at org.junit.jupiter.engine.descriptor.JupiterTestDescriptor.<init>(JupiterTestDescriptor.java:69)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.<init>(ClassBasedTestDescriptor.java:100)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.<init>(ClassTestDescriptor.java:51)
at org.junit.jupiter.engine.discovery.ClassSelectorResolver.newClassTestDescriptor(ClassSelectorResolver.java:119)
at org.junit.jupiter.engine.discovery.ClassSelectorResolver.lambda$resolve$5(ClassSelectorResolver.java:98)
at org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$700/0x000000010180db60.apply(Unknown Source)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$DefaultContext.createAndAdd(EngineDiscoveryRequestResolution.java:250)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$DefaultContext.addToParent(EngineDiscoveryRequestResolution.java:213)
at org.junit.jupiter.engine.discovery.ClassSelectorResolver.lambda$resolve$6(ClassSelectorResolver.java:98)
at org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$699/0x000000010180d918.apply(Unknown Source)
at java.util.Optional.map(Optional.java:260)
at org.junit.jupiter.engine.discovery.ClassSelectorResolver.resolve(ClassSelectorResolver.java:96)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.lambda$resolveUniqueId$3(EngineDiscoveryRequestResolution.java:176)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$685/0x000000010180e248.apply(Unknown Source)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1602)
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:189)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolveUniqueId(EngineDiscoveryRequestResolution.java:176)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:124)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.access$100(EngineDiscoveryRequestResolution.java:58)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$DefaultContext.resolve(EngineDiscoveryRequestResolution.java:228)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$DefaultContext.addToParent(EngineDiscoveryRequestResolution.java:222)
at org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType.resolveUniqueIdIntoTestDescriptor(MethodSelectorResolver.java:224)
at org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType.access$200(MethodSelectorResolver.java:164)
at org.junit.jupiter.engine.discovery.MethodSelectorResolver.lambda$resolve$4(MethodSelectorResolver.java:117)
at org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$687/0x000000010180e6e0.apply(Unknown Source)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.util.Spliterators$ArraySpliterator.tryAdvance(Spliterators.java:1002)
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647)
at org.junit.jupiter.engine.discovery.MethodSelectorResolver.resolve(MethodSelectorResolver.java:133)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.lambda$resolveUniqueId$3(EngineDiscoveryRequestResolution.java:176)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$685/0x000000010180e248.apply(Unknown Source)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1602)
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:647)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:189)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolveUniqueId(EngineDiscoveryRequestResolution.java:176)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolve(EngineDiscoveryRequestResolution.java:124)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.resolveCompletely(EngineDiscoveryRequestResolution.java:92)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution.run(EngineDiscoveryRequestResolution.java:83)
at org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver.resolve(EngineDiscoveryRequestResolver.java:113)
at org.junit.jupiter.engine.discovery.DiscoverySelectorResolver.resolveSelectors(DiscoverySelectorResolver.java:46)
at org.junit.jupiter.engine.JupiterTestEngine.discover(JupiterTestEngine.java:69)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverEngineRoot(EngineDiscoveryOrchestrator.java:152)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discoverSafely(EngineDiscoveryOrchestrator.java:132)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discover(EngineDiscoveryOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineDiscoveryOrchestrator.discover(EngineDiscoveryOrchestrator.java:78)
at org.junit.platform.launcher.core.DefaultLauncher.discover(DefaultLauncher.java:110)
at org.junit.platform.launcher.core.DefaultLauncher.discover(DefaultLauncher.java:78)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.discover(DefaultLauncherSession.java:81)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.discover(SessionPerRequestLauncher.java:46)
at org.graalvm.junit.platform.JUnitPlatformFeature.discoverTestsAndRegisterTestClassesForReflection(JUnitPlatformFeature.java:135)
at org.graalvm.junit.platform.JUnitPlatformFeature.beforeAnalysis(JUnitPlatformFeature.java:94)
at com.oracle.svm.hosted.NativeImageGenerator.lambda$runPointsToAnalysis$9(NativeImageGenerator.java:736)
at com.oracle.svm.hosted.NativeImageGenerator$$Lambda$500/0x000000010179ed48.accept(Unknown Source)
at com.oracle.svm.hosted.FeatureHandler.forEachFeature(FeatureHandler.java:85)
at com.oracle.svm.hosted.NativeImageGenerator.runPointsToAnalysis(NativeImageGenerator.java:736)
at com.oracle.svm.hosted.NativeImageGenerator.doRun(NativeImageGenerator.java:578)
at com.oracle.svm.hosted.NativeImageGenerator.run(NativeImageGenerator.java:535)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:403)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:580)
at com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:128)
It looks like AutoConfigureTestDatabase#connection is the culprit.
Comment From: mhalbritter
There are two issues in GraalVM which trigger this bug: https://github.com/oracle/graal/issues/5300 and https://github.com/oracle/graal/issues/5301.
We can workaround the lambda one.
Another workaround for the whole issue would be
--initialize-at-build-time=org.springframework.boot.jdbc.EmbeddedDatabaseConnection
as native image args, but we don't want to rely on build time init.
Comment From: mhalbritter
I've found a way to workaround both GraalVM problems. They only appear if the ctor of the enum is used. when we use a switch inside the enums method, the problem goes away. See https://github.com/mhalbritter/spring-boot/commit/ee5aaaaa7a7b6dc726d7060953f66b07ee45f634 for details.