oracle / graal

GraalVM compiles Java applications into native executables that start instantly, scale fast, and use fewer compute resources 🚀

Home Page:https://www.graalvm.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

No-fallback native image - Cannot instantiate class: org.eclipse.jetty.jndi.InitialContextFactory

MusicDin opened this issue · comments

Describe the issue
When building no-fallback native-image there is no error. But when image is run I get the following error:

2020-05-17 10:46:17.712 WARNING -- org.eclipse.jetty.webapp.WebAppContext -- Failed startup of context o.e.j.w.WebAppContext@3fa7964{/,file:///var/tmp/kumuluzee-tmp-webapp12797499415240148367/,UNAVAILABLE}
javax.naming.NoInitialContextException: Cannot instantiate class: org.eclipse.jetty.jndi.InitialContextFactory [Root exception is java.lang.ClassNotFoundException: org.eclipse.jetty.jndi.InitialContextFactory]
	at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:719)
	at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305)
	at javax.naming.InitialContext.init(InitialContext.java:236)
	at javax.naming.InitialContext.<init>(InitialContext.java:184)
	at org.eclipse.jetty.plus.webapp.EnvConfiguration.createEnvContext(EnvConfiguration.java:257)
	at org.eclipse.jetty.plus.webapp.EnvConfiguration.preConfigure(EnvConfiguration.java:67)
	at org.eclipse.jetty.webapp.WebAppContext.preConfigure(WebAppContext.java:506)
	at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:544)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:138)
	at org.eclipse.jetty.server.Server.start(Server.java:415)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:108)
	at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
	at org.eclipse.jetty.server.Server.doStart(Server.java:382)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at com.kumuluz.ee.jetty.JettyServletServer.startServer(JettyServletServer.java:83)
	at com.kumuluz.ee.EeApplication.initialize(EeApplication.java:375)
	at com.kumuluz.ee.EeApplication.<init>(EeApplication.java:73)
	at com.kumuluz.ee.EeApplication.main(EeApplication.java:85)
Caused by: java.lang.ClassNotFoundException: org.eclipse.jetty.jndi.InitialContextFactory
	at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:60)
	at java.lang.Class.forName(DynamicHub.java:1224)
	at com.sun.naming.internal.VersionHelper.loadClass(VersionHelper.java:123)
	at com.sun.naming.internal.VersionHelper.loadClass(VersionHelper.java:96)
	at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:716)
	... 18 more

For generating configuration files I'm using tracing agent.

Steps to reproduce the issue
Please include both build steps as well as run steps

  1. git clone https://github.com/MusicDin/graalvm-project.git
  2. mvn clean package
  3. java -agentlib:native-image-agent=config-output-dir=api/src/main/resources/META-INF/native-image -cp api/target/classes:api/target/dependency/* com.kumuluz.ee.EeApplication
native-image --no-fallback \
  --allow-incomplete-classpath \
  -H:+ReportUnsupportedElementsAtRuntime \
  -H:+ReportExceptionStackTraces \
  -H:+PrintClassInitialization \
  -H:EnableURLProtocols=http,https \
  -H:Log=registerResource \
  -H:ReflectionConfigurationFiles=api/src/main/resources/META-INF/native-image/reflect-config.json \
  -H:ResourceConfigurationFiles=api/src/main/resources/META-INF/native-image/resource-config.json \
  -cp api/target/classes:api/target/dependency/* com.kumuluz.ee.EeApplication graalvm-basic
  1. Run the image: ./graalvm-basic

At the 3. step I also tried calling http://localhost:8080/v1/test and http://localhost:8080/servlet while tracing agent was running.

Describe GraalVM and your environment:

  • OS: Tried on Ubuntu and Manjaro
  • JDK: openJDK 11
  • GraalVM version:
openjdk 11.0.6 2020-01-14
OpenJDK Runtime Environment GraalVM CE 20.0.0 (build 11.0.6+9-jvmci-20.0-b02)
OpenJDK 64-Bit Server VM GraalVM CE 20.0.0 (build 11.0.6+9-jvmci-20.0-b02, mixed mode, sharing)
  • Framework: KumuluzEE
  • Arhitecture: AMD64

The problem is that your application makes use of org.eclipse.jetty.jndi.InitialContextFactory but when you built the image that class was nowhere to be found in the your -cp api/target... argument.

To find such issues already at build time you have to remove -H:+ReportUnsupportedElementsAtRuntime. native-image will then tell you which classes you do not have on the classpath that are referred to by your application.

Thank you for quick reply.

So is there any way to explicitly configure or add dependencies. As application is fully functional when run on it's own, it's quite interesting that dependency is not present on build time.

Also I built image again without -H:+ReportUnsupportedElementsAtRuntime tag and posted log here to keep issue as clean as possible: https://github.com/MusicDin/graalvm-project/blob/master/logs/ErrorNoTag_ReportUnsupportedElementsAtRunTime.txt

Thank you in advance.

possible: https://github.com/MusicDin/graalvm-project/blob/master/logs/ErrorNoTag_ReportUnsupportedElementsAtRunTime.txt

org.jvnet.hk2.internal.ProxyUtilities$4.run(ProxyUtilities.java:148) is causing trouble. That's a Runnable that the static analysis unfortunately thinks is reachable (our analysis is context-insensitive and thinks every observed Runnable could be called from every java.lang.Runnable#run call site). It seems org.jvnet.hk2.internal.ProxyUtilities makes use of runtime classloading which is something native-images cannot support (closed word assumption) at image runtime.

You can use image-built-time execution to do your dependency configuration but the final image cannot have dynamic dependency configuration. See https://github.com/graalvm/graalvm-demos/tree/master/native-image-configure-examples

Hello again.

I tried implementing your recommendation, but I think problem resides in web.xml not being included properly.

KumuluzEE requires web.xml in order to run and if it is not provided it generates one itself. I include web.xml in order to prevent KumuluzEE generating it. And when application is run (normaly, not as native-image) the output looks something like this:

org.eclipse.jetty.server.handler.ContextHandler -- Started o.e.j.w.WebAppContext@120f102b{/,file:///home/graaluser/graalvm-project/api/target/classes/webapp/,AVAILABLE}

But when no-fallback image is run the output looks like this:

org.eclipse.jetty.webapp.WebAppContext -- Failed startup of context o.e.j.w.WebAppContext@391655cc{/,file:///home/graaluser/graalvm-project/api/target/classes/webapp/,UNAVAILABLE}

So my guess is that consequence of not including web.xml properly leads to errors that you have recognized in previous answers.

In order to fix this problem I tried using -H:IncludeResources= tag to add web.xml and than checked output of -H:Log=registerResource: tag and web.xml was not present in it.

Am I including descriptor wrong? And is it possible that the errors are consequence of web.xml not being included correctly?

Also if it helps, here is link to code where KumuluzEE handles web.xml descriptor:
https://github.com/kumuluz/kumuluzee/blob/master/common/src/main/java/com/kumuluz/ee/common/utils/ResourceUtils.java

Thank you in advance.

Also if it helps, here is link to code where KumuluzEE handles web.xml descriptor:
https://github.com/kumuluz/kumuluzee/blob/master/common/src/main/java/com/kumuluz/ee/common/utils/ResourceUtils.java

This code will not work as image

https://github.com/kumuluz/kumuluzee/blob/0c097aa239d3f7515ef38f9f506fce7d6e990530/common/src/main/java/com/kumuluz/ee/common/utils/ResourceUtils.java#L51

While we can include resources in images we can only do it for files/data. Trying to include a directory as a resource is currently not supported.

But in my case when I normally run it, web.xml is found, so the class is left on this line:
https://github.com/kumuluz/kumuluzee/blob/0c097aa239d3f7515ef38f9f506fce7d6e990530/common/src/main/java/com/kumuluz/ee/common/utils/ResourceUtils.java#L47

If I understand correctly, only one file can be included and if this segment of code would be reached, it would not cause problems as line you pointed out could not be reached.

But when image is generated, it passes the first segment of the code and reaches the part where empty web.xml is generated in temporary folder:
https://github.com/kumuluz/kumuluzee/blob/0c097aa239d3f7515ef38f9f506fce7d6e990530/common/src/main/java/com/kumuluz/ee/common/utils/ResourceUtils.java#L95

Is there a reason that GraalVM is not including that file?
My assumption is that it checks only linked files, and web.xml is not being linked.

If so, how can I include this exact file?
It seems as that goal is not achived using -H:IncludeResources tag.

Hope I didn't go too much out of scope of GralVM.