Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[native-image] Failed to compile spring-boot project to native image (UnsupportedFeatureException) #348

Closed
daniel-frank opened this issue Apr 18, 2018 · 12 comments
Assignees

Comments

@daniel-frank
Copy link

I'm trying to compile a 'simple' spring-boot web project to native image.
Project source:
https://drive.google.com/file/d/136E00Gux6vL3tvcZFM3KgcNuIvtXWlj1/view?usp=sharing

Command:
native-image -jar graal-0.0.1-SNAPSHOT.jar

Log:

Build on Server(pid: 25018, port: 26682)*
   classlist:   1,200.03 ms
       (cap):   1,115.73 ms
       setup:   2,508.68 ms
    analysis:   8,853.48 ms
error: unsupported features in 3 methods
Detailed message:
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Unsupported constructor java.lang.ClassLoader.<init>(ClassLoader) is reachable: The declaring class of this element has been substituted, but this element is not present in the substitution class
To diagnose the issue, you can add the option -H:+ReportUnsupportedElementsAtRuntime. The unsupported element is then reported at run time when it is accessed the first time.
Trace: 
	at parsing java.security.SecureClassLoader.<init>(SecureClassLoader.java:76)
Call path from entry point to java.security.SecureClassLoader.<init>(ClassLoader): 
	at java.security.SecureClassLoader.<init>(SecureClassLoader.java:76)
	at java.net.URLClassLoader.<init>(URLClassLoader.java:100)
	at org.springframework.boot.loader.LaunchedURLClassLoader.<init>(LaunchedURLClassLoader.java:50)
	at org.springframework.boot.loader.Launcher.createClassLoader(Launcher.java:74)
	at org.springframework.boot.loader.Launcher.createClassLoader(Launcher.java:64)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:49)
	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
	at com.oracle.svm.reflect.proxies.Proxy_1_JarLauncher_main.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:199)
	at Lcom/oracle/svm/core/code/CEntryPointCallStubs;.com_002eoracle_002esvm_002ecore_002eJavaMainWrapper_002erun_0028int_002corg_002egraalvm_002enativeimage_002ec_002etype_002eCCharPointerPointer_0029(generated:0)
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Unsupported field java.net.URL.handlers is reachable
To diagnose the issue, you can add the option -H:+ReportUnsupportedElementsAtRuntime. The unsupported element is then reported at run time when it is accessed the first time.
Trace: 
	at parsing java.net.URL.setURLStreamHandlerFactory(URL.java:1118)
Call path from entry point to java.net.URL.setURLStreamHandlerFactory(URLStreamHandlerFactory): 
	at java.net.URL.setURLStreamHandlerFactory(URL.java:1110)
	at org.springframework.boot.loader.jar.JarFile.resetCachedUrlHandlers(JarFile.java:392)
	at org.springframework.boot.loader.jar.JarFile.registerUrlProtocolHandler(JarFile.java:382)
	at org.springframework.boot.loader.Launcher.launch(Launcher.java:48)
	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
	at com.oracle.svm.reflect.proxies.Proxy_1_JarLauncher_main.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:199)
	at Lcom/oracle/svm/core/code/CEntryPointCallStubs;.com_002eoracle_002esvm_002ecore_002eJavaMainWrapper_002erun_0028int_002corg_002egraalvm_002enativeimage_002ec_002etype_002eCCharPointerPointer_0029(generated:0)
Error: com.oracle.graal.pointsto.constraints.UnsupportedFeatureException: Unsupported method java.security.ProtectionDomain.getCodeSource() is reachable: The declaring class of this element has been substituted, but this element is not present in the substitution class
To diagnose the issue, you can add the option -H:+ReportUnsupportedElementsAtRuntime. The unsupported element is then reported at run time when it is accessed the first time.
Trace: 
	at parsing org.springframework.boot.loader.Launcher.createArchive(Launcher.java:118)
Call path from entry point to org.springframework.boot.loader.Launcher.createArchive(): 
	at org.springframework.boot.loader.Launcher.createArchive(Launcher.java:117)
	at org.springframework.boot.loader.ExecutableArchiveLauncher.<init>(ExecutableArchiveLauncher.java:38)
	at org.springframework.boot.loader.JarLauncher.<init>(JarLauncher.java:35)
	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
	at com.oracle.svm.reflect.proxies.Proxy_1_JarLauncher_main.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:199)
	at Lcom/oracle/svm/core/code/CEntryPointCallStubs;.com_002eoracle_002esvm_002ecore_002eJavaMainWrapper_002erun_0028int_002corg_002egraalvm_002enativeimage_002ec_002etype_002eCCharPointerPointer_0029(generated:0)

Error: Processing image build request failed
@cstancu cstancu self-assigned this Apr 18, 2018
@cstancu
Copy link
Member

cstancu commented Apr 20, 2018

Thank you for your report. Spring-boot uses dynamic class loading which is a limitation of SubstrateVM. Sometimes it is possible to avoid dynamic class loading (which might reduce some functionality). I will look into this possibility for spring-boot.

@dsyer
Copy link

dsyer commented May 11, 2018

You can get past this specific error by not using the fat jar launcher as a main method. But there are other bogies lurking. Spring Boot has a static (but optional) dependency on Groovy, for example, so even though it will never be used at runtime, a native-image cannot be built because groovy.lang.Closure is not available for a vanilla app. If you add Groovy to the classpath (even though it will not be used) you can get past that, but the build fails again because of a java.lang.ClassCastException: jdk.vm.ci.hotspot.HotSpotUnresolvedJavaType cannot be cast to jdk.vm.ci.meta.ResolvedJavaType. I managed to build a binary image by creating a dummy, empty interface called groovy.lang.Closure and putting that on the classpath instead of the real groovy. Then the image fails at runtime because of an issue with java.lang.reflect.Proxy (I'll open a separate ticket about that because it might be interesting on its own).

@cstancu
Copy link
Member

cstancu commented May 12, 2018

@dsyer can you provide the trace for the java.lang.ClassCastException: jdk.vm.ci.hotspot.HotSpotUnresolvedJavaType cannot be cast to jdk.vm.ci.meta.ResolvedJavaType that you mention above? Thank you!

@dsyer
Copy link

dsyer commented May 12, 2018

Sure:

$ native-image -cp ~/.sdkman/candidates/groovy/3.0.0-alpha-2/lib/groovy-3.0.0-alpha-2.jar:$CLASSPATH --no-server -H:Name=hello com.example.LauncherApplication -H:+ReportUnsupportedElementsAtRuntime
   classlist:   2,997.09 ms
       (cap):     868.76 ms
       setup:   1,770.21 ms
    analysis:   7,681.46 ms
fatal error: org.graalvm.compiler.java.BytecodeParser$BytecodeParserError: java.lang.ClassCastException: jdk.vm.ci.hotspot.HotSpotUnresolvedJavaType cannot be cast to jdk.vm.ci.meta.ResolvedJavaType
	at parsing org.springframework.beans.factory.groovy.GroovyDynamicElementReader.invokeMethod(GroovyDynamicElementReader.groovy:75)
	at org.graalvm.compiler.java.BytecodeParser.throwParserError(BytecodeParser.java:2339)
	at com.oracle.svm.hosted.phases.SharedGraphBuilderPhase$SharedBytecodeParser.throwParserError(SharedGraphBuilderPhase.java:92)
	at org.graalvm.compiler.java.BytecodeParser.iterateBytecodesForBlock(BytecodeParser.java:3070)
	at org.graalvm.compiler.java.BytecodeParser.processBlock(BytecodeParser.java:2886)
	at org.graalvm.compiler.java.BytecodeParser.build(BytecodeParser.java:880)
	at org.graalvm.compiler.java.BytecodeParser.buildRootMethod(BytecodeParser.java:774)
	at org.graalvm.compiler.java.GraphBuilderPhase$Instance.run(GraphBuilderPhase.java:93)
	at org.graalvm.compiler.phases.Phase.run(Phase.java:47)
	at org.graalvm.compiler.phases.BasePhase.apply(BasePhase.java:195)
	at org.graalvm.compiler.phases.Phase.apply(Phase.java:40)
	at org.graalvm.compiler.phases.Phase.apply(Phase.java:36)
	at com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.parse(MethodTypeFlowBuilder.java:195)
	at com.oracle.graal.pointsto.flow.MethodTypeFlowBuilder.apply(MethodTypeFlowBuilder.java:319)
	at com.oracle.graal.pointsto.flow.MethodTypeFlow.doParse(MethodTypeFlow.java:308)
	at com.oracle.graal.pointsto.flow.MethodTypeFlow.ensureParsed(MethodTypeFlow.java:298)
	at com.oracle.graal.pointsto.flow.MethodTypeFlow.addContext(MethodTypeFlow.java:105)
	at com.oracle.graal.pointsto.DefaultAnalysisPolicy$DefaultVirtualInvokeTypeFlow.onObservedUpdate(DefaultAnalysisPolicy.java:184)
	at com.oracle.graal.pointsto.flow.TypeFlow.notifyObservers(TypeFlow.java:345)
	at com.oracle.graal.pointsto.flow.TypeFlow.update(TypeFlow.java:387)
	at com.oracle.graal.pointsto.BigBang$2.run(BigBang.java:498)
	at com.oracle.graal.pointsto.util.CompletionExecutor.lambda$execute$0(CompletionExecutor.java:172)
	at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1402)
	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: java.lang.ClassCastException: jdk.vm.ci.hotspot.HotSpotUnresolvedJavaType cannot be cast to jdk.vm.ci.meta.ResolvedJavaType
	at com.oracle.graal.pointsto.infrastructure.WrappedConstantPool.lookupConstant(WrappedConstantPool.java:140)
	at org.graalvm.compiler.java.BytecodeParser.lookupConstant(BytecodeParser.java:3828)
	at org.graalvm.compiler.java.BytecodeParser.genLoadConstant(BytecodeParser.java:3566)
	at org.graalvm.compiler.java.BytecodeParser.processBytecode(BytecodeParser.java:4513)
	at org.graalvm.compiler.java.BytecodeParser.iterateBytecodesForBlock(BytecodeParser.java:3065)
	... 23 more
Error: Image building with exit status 1

@tdanylchuk
Copy link

is there any other workaround for building native-image for spring boot app, or for now it's blocked w\o any hopes?

@dsyer
Copy link

dsyer commented Jun 29, 2018

There's no way yet to run a Spring Boot application. Not even the GenericConversionService from spring-core will work in a native image right now I think, so that's a blocker for a large class of Spring applications (not just Spring Boot). The Graal team have said they are interested in making it work though, so I wouldn't say there is no hope, but certainly it is blocked on this and other issues.

@tdanylchuk
Copy link

tdanylchuk commented Jun 29, 2018

Well, GraalVM looks promising for microservices world, since services are getting fat and start time is increasing, which breaks one of the microservices paradigm - fast startup.
Since most of the microsevices in java are build upon Spring Boot it's crucial to have possibility to build native image from it.
I would like to use/test as soon issues with spring will be resolved.
Can we make this issue/thread main for spring/boot? :D
Looking forward! Thanks!

@sdeleuze
Copy link
Collaborator

sdeleuze commented Jul 2, 2018

See #507 about the ConversionService issue.

@sdeleuze
Copy link
Collaborator

sdeleuze commented Jul 2, 2018

I have created SPR-16991 to track SubstrateVM Spring support status.

@adamsiemion
Copy link

adamsiemion commented Jul 2, 2018

More than a week ago Josh Long at the beginning of his Devoxx (devoxx.pl) talk demoed a Spring Boot/Fu app built as a native image using GraalVM: spring-projects-experimental/spring-fu#29

@dsyer
Copy link

dsyer commented Jul 3, 2018

@joshlong used the Kotlin sample app from here: spring-projects-experimental/spring-fu#29. There's another minimal Spring app in Java here that works: https://github.com/dsyer/spring-boot-micro-apps (see the instructions in the README). Neither of those apps uses Spring Boot.

@cstancu
Copy link
Member

cstancu commented Mar 14, 2019

The originally reported issue has been fixed. With the latest release, you can build an image using native-image --report-unsupported-elements-at-runtime -jar build/libs/graal-0.0.1-SNAPSHOT.jar. However, running the image I get:

$ ./graal-0.0.1-SNAPSHOT 
Exception in thread "main" java.lang.IllegalStateException: java.lang.IllegalStateException: Unable to determine code source archive
	at org.springframework.boot.loader.ExecutableArchiveLauncher.<init>(ExecutableArchiveLauncher.java:41)
	at org.springframework.boot.loader.JarLauncher.<init>(JarLauncher.java:35)
	at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
Caused by: java.lang.IllegalStateException: Unable to determine code source archive
	at org.springframework.boot.loader.Launcher.createArchive(Launcher.java:122)
	at org.springframework.boot.loader.ExecutableArchiveLauncher.<init>(ExecutableArchiveLauncher.java:38)
	... 2 more

It looks like the example app tries to execute a jar which is currently not supported with native-image.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants