quarkus: Quarkus cannot load Truffle/polyglot languages with the custom class loader.

Describe the bug

With GraalVM 23.1 (GraalVM for JDK 21) GraalVM Truffle/Polyglot languages are now consumed from the class/module-path. For context, this project is also known as Truffle Unchained, and we wrote up all about it here: https://medium.com/graalvm/truffle-unchained-13887b77b62c

For that to work we require that the optimizing Truffle runtime runs as a named module. The reason is that we would otherwise need to export the internal JVMCI API to ALL-UNNAMED. The JVMCI is unsafe on steroids and must not be exported like this to preserve VM integrity.

There is no problem with regular Java applications that leverage the module-path or use a module class loader as the truffle runtime runs as named module. As far as I understand Quarkus cannot run modules as named modules atm, therefore this solution cannot be applied. But please correct me if I am wrong.

When running languages from the classpath the Polyglot runtime automatically scans the classpath and looks for modular jar files that it can spawn on a separate module-layer + classloader. This approach typically works for regular Java SE applications, but it fails with the custom Quarkus class loader.

This issue is intended to start a discussion on how we can solve this problem.

Here are a few suggestions/ideas:

  • Create an integration API on our end that Quarkus can integrate into that we can use to enumerate the class path.
  • Quarkus extends the URLClassLoader that Truffle is able to understand enumerate jar files from.
  • Quarkus keeps the System.getProperty("java.class.path") that allows us to spawn our layer.

I discussed this issue with @maxandersen at the GraalVM meetup.

Expected behavior

The page should render without error and no warning should be printed that optimizations are disabled.

Actual behavior

~/g/1/f/embedding-quarkus $ $JAVA_HOME/bin/java -Dpolyglotimpl.TraceClassPathIsolation=true -jar ./target/quarkus-app/quarkus-run.jar
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2023-10-02 14:09:44,024 INFO  [io.quarkus] (main) embedding 1.0.0-SNAPSHOT on JVM (powered by Quarkus 3.4.1) started in 0.382s. Listening on: http://0.0.0.0:8080
2023-10-02 14:09:44,026 INFO  [io.quarkus] (main) Profile prod activated.
2023-10-02 14:09:44,026 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy-reactive, smallrye-context-propagation, vertx]
[class-path-isolation] Start polyglot class-path isolation
[class-path-isolation] Collected 1 class-path entries from java.class.path system property
[class-path-isolation] Class-path entry: ./target/quarkus-app/quarkus-run.jar
[class-path-isolation] No truffle-api and/or polyglot found on classpath.
2023-10-02 14:10:09,738 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-1) HTTP Request to /hello failed, error id: 794662c0-106c-4404-a176-d7c04c4a0e50-1: java.lang.IllegalStateException: No language and polyglot implementation was found on the class-path. Make sure at last one language is added on the class-path. If you put a language on the class-path and you encounter this error then there could be a problem with isolated class loading. Use -Dpolyglotimpl.TraceClassPathIsolation=true to debug class loader islation problems. For best performance it is recommended to use polyglot from the module-path instead of the class-path.
	at org.graalvm.polyglot.Engine$PolyglotInvalid.noPolyglotImplementationFound(Engine.java:2071)
	at org.graalvm.polyglot.Engine$PolyglotInvalid.createHostAccess(Engine.java:2057)
	at org.graalvm.polyglot.Engine$PolyglotInvalid.createHostAccess(Engine.java:2023)
	at org.graalvm.polyglot.Engine$Builder.build(Engine.java:753)
	at org.graalvm.polyglot.Context$Builder.build(Context.java:1925)
	at org.graalvm.polyglot.Context.create(Context.java:979)
	at org.quarkus.GreetingResource.hello(GreetingResource.java:15)
	at org.quarkus.GreetingResource$quarkusrestinvoker$hello_e747664148511e1e5212d3e0f4b40d45c56ab8a1.invoke(Unknown Source)
	at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
	at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
	at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:1583)

There is a second issue if you uncomment the test code in the attached test project and run mvn package you get:

[ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 2.935 s <<< FAILURE! -- in org.quarkus.GreetingResourceTest
[ERROR] org.quarkus.GreetingResourceTest.testHelloEndpoint -- Time elapsed: 0.713 s <<< FAILURE!
java.lang.AssertionError:
1 expectation failed.
Expected status code <200> but was <500>.

	at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
	at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:73)
	at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:108)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:57)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:263)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:277)
	at io.restassured.internal.ResponseSpecificationImpl$HamcrestAssertionClosure.validate(ResponseSpecificationImpl.groovy:512)
	at io.restassured.internal.ResponseSpecificationImpl$HamcrestAssertionClosure$validate$1.call(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139)
	at io.restassured.internal.ResponseSpecificationImpl.validateResponseIfRequired(ResponseSpecificationImpl.groovy:696)
	at io.restassured.internal.ResponseSpecificationImpl.this$2$validateResponseIfRequired(ResponseSpecificationImpl.groovy)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:43)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:198)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:62)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:171)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:185)
	at io.restassured.internal.ResponseSpecificationImpl.statusCode(ResponseSpecificationImpl.groovy:135)
	at io.restassured.specification.ResponseSpecification$statusCode$0.callCurrent(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:171)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:185)
	at io.restassured.internal.ResponseSpecificationImpl.statusCode(ResponseSpecificationImpl.groovy:143)
	at io.restassured.internal.ValidatableResponseOptionsImpl.statusCode(ValidatableResponseOptionsImpl.java:89)
	at org.quarkus.GreetingResourceTest.testHelloEndpoint(GreetingResourceTest.java:18)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at io.quarkus.test.junit.QuarkusTestExtension.runExtensionMethod(QuarkusTestExtension.java:1015)
	at io.quarkus.test.junit.QuarkusTestExtension.interceptTestMethod(QuarkusTestExtension.java:829)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.apache.maven.surefire.junitplatform.LazyLauncher.execute(LazyLauncher.java:56)
	at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.execute(JUnitPlatformProvider.java:184)
	at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invokeAllTests(JUnitPlatformProvider.java:148)
	at org.apache.maven.surefire.junitplatform.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:122)
	at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
	at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
	at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
	at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
	Suppressed: java.lang.InternalError: java.lang.reflect.InvocationTargetException
		at org.graalvm.polyglot.Engine$ClassPathIsolation.createIsolatedTruffle(Engine.java:1756)
		at org.graalvm.polyglot.Engine$1.searchServiceLoader(Engine.java:1682)
		at org.graalvm.polyglot.Engine$1.run(Engine.java:1668)
		at org.graalvm.polyglot.Engine$1.run(Engine.java:1663)
		at java.base/java.security.AccessController.doPrivileged(AccessController.java:319)
		at org.graalvm.polyglot.Engine.initEngineImpl(Engine.java:1663)
		at org.graalvm.polyglot.Engine$ImplHolder.<clinit>(Engine.java:186)
		at org.graalvm.polyglot.Engine.getImpl(Engine.java:438)
		at org.graalvm.polyglot.Engine$Builder.build(Engine.java:736)
		at org.graalvm.polyglot.Context$Builder.build(Context.java:1925)
		at org.graalvm.polyglot.Context.create(Context.java:979)
		at org.quarkus.GreetingResource.hello(GreetingResource.java:15)
		at org.quarkus.GreetingResource$quarkusrestinvoker$hello_e747664148511e1e5212d3e0f4b40d45c56ab8a1.invoke(Unknown Source)
		at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
		at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
		at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
		at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:582)
		at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
		at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
		at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
		at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
		at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
		at java.base/java.lang.Thread.run(Thread.java:1583)
	Caused by: java.lang.reflect.InvocationTargetException
		at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:118)
		at java.base/java.lang.reflect.Method.invoke(Method.java:580)
		at org.graalvm.polyglot.Engine$ClassPathIsolation.createIsolatedTruffle(Engine.java:1753)
		... 22 more
	Caused by: java.lang.IllegalAccessError: superinterface check failed: class com.oracle.truffle.runtime.hotspot.libgraal.LibGraalTruffleCompilationSupport (in module org.graalvm.truffle.runtime) cannot access class com.oracle.truffle.compiler.TruffleCompilationSupport (in unnamed module @0x455cbf18) because module org.graalvm.truffle.runtime does not read unnamed module @0x455cbf18
		at java.base/java.lang.ClassLoader.defineClass1(Native Method)
		at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1027)
		at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1105)
		at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:182)
		at java.base/jdk.internal.loader.Loader.defineClass(Loader.java:612)
		at java.base/jdk.internal.loader.Loader.lambda$findClassInModuleOrNull$6(Loader.java:589)
		at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
		at java.base/jdk.internal.loader.Loader.findClassInModuleOrNull(Loader.java:590)
		at java.base/jdk.internal.loader.Loader.loadClass(Loader.java:548)
		at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
		at org.graalvm.truffle.runtime/com.oracle.truffle.runtime.hotspot.HotSpotTruffleRuntimeAccess.createRuntime(HotSpotTruffleRuntimeAccess.java:113)
		at org.graalvm.truffle.runtime/com.oracle.truffle.runtime.hotspot.HotSpotTruffleRuntimeAccess.getRuntime(HotSpotTruffleRuntimeAccess.java:64)
		at org.graalvm.truffle/com.oracle.truffle.api.Truffle.createRuntime(Truffle.java:142)
		at org.graalvm.truffle/com.oracle.truffle.api.Truffle$1.run(Truffle.java:173)
		at org.graalvm.truffle/com.oracle.truffle.api.Truffle$1.run(Truffle.java:171)
		at java.base/java.security.AccessController.doPrivileged(AccessController.java:319)
		at org.graalvm.truffle/com.oracle.truffle.api.Truffle.initRuntime(Truffle.java:171)
		at org.graalvm.truffle/com.oracle.truffle.api.Truffle.<clinit>(Truffle.java:63)
		at com.oracle.truffle.enterprise/com.oracle.truffle.runtime.enterprise.EnterpriseTruffle.G(stripped:21)
		at com.oracle.truffle.enterprise/com.oracle.truffle.polyglot.enterprise.EnterprisePolyglotImpl.getPriority(stripped:496)
		at java.base/java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:473)
		at java.base/java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
		at java.base/java.util.TimSort.sort(TimSort.java:220)
		at java.base/java.util.Arrays.sort(Arrays.java:1308)
		at java.base/java.util.ArrayList.sort(ArrayList.java:1804)
		at java.base/java.util.Collections.sort(Collections.java:178)
		at org.graalvm.polyglot/org.graalvm.polyglot.Engine.loadAndValidateProviders(Engine.java:1632)
		at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
		... 24 more

I think what is going on is that the the truffle-compiler.jar that already ships as part of the GraalVM JDK is loaded with the Quarkus classloader.

How to Reproduce?

  1. Download and unpack: embedding-quarkus.zip

  2. Download and unpack GraalVM for JDK 21 and set your JAVA_HOME to it.

  3. Run: mvn quarkus:dev

  4. Open http://0.0.0.0:8080/hello

To reproduce the second issue uncomment the code in GreetingResourceTest and run mvn package.

Output of uname -a or ver

Darwin christianhumer-mac 22.6.0 Darwin Kernel Version 22.6.0: Wed Jul 5 22:22:05 PDT 2023; root:xnu-8796.141.3~6/RELEASE_ARM64_T6000 arm64

Output of java -version

java version “21” 2023-09-19 Java™ SE Runtime Environment Oracle GraalVM 21+35.1 (build 21+35-jvmci-23.1-b15) Java HotSpot™ 64-Bit Server VM Oracle GraalVM 21+35.1 (build 21+35-jvmci-23.1-b15, mixed mode, sharing)

GraalVM version (if different from Java)

23.1 / GraalVM for JDK 21

Quarkus version or git rev

3.4.1

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

Maven home: /opt/homebrew/Cellar/maven/3.9.4/libexec Java version: 21, vendor: Oracle Corporation, runtime: /Users/christianhumer/graal/graalvm/graalvm-ee-java21-23.1.0 Default locale: en_CH, platform encoding: UTF-8 OS name: “mac os x”, version: “13.5.2”, arch: “aarch64”, family: “mac”

Additional information

Related micronaut issue: https://github.com/micronaut-projects/micronaut-maven-plugin/issues/866

About this issue

  • Original URL
  • State: closed
  • Created 9 months ago
  • Comments: 27 (20 by maintainers)

Commits related to this issue

Most upvoted comments

Thanks for the detailed report, much appreciated!

From the options presented, I think that only 1 is possible for our case.

Let’s also include @zakkak here

We would essentially set java.class.path under the hood. The problem is that it needs to be done for each mode Quarkus supports but I manually tested that it works…

That is an interesting idea indeed. I was hoping for a solution like this. Let me know if I can help.

@zakkak I’ve commented here https://github.com/graalvm/mandrel-packaging/pull/369#issuecomment-1755992204 on how to enable Truffle languages for Mandrel native-image builds.