Skip to content

ClassNotFoundException with certain Gradle multi-project setup and dev mode #48100

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

Open
reaver585 opened this issue May 27, 2025 · 1 comment
Labels
area/devmode area/gradle Gradle kind/bug Something isn't working

Comments

@reaver585
Copy link

Describe the bug

Howdy everyone.
Imagine the following project setup (with Gradle):

3 projects on the top level

  • :runner -> this is a minimal Quarkus app with REST extension and a single stub endpoint, and it depends on
  • :project-a, which has a single class, and this project depends on
  • :project-b, which has a single class and no additional dependencies

Additionally, :project-a does configure the jar task in the following way:

jar {
    archiveClassifier = "something"
    archiveBaseName = "project-a"
}

Expected behavior

My expectation is that when I call an endpoint from the :runner project, it does not throw and does the work it needs to do.

Actual behavior

When the :runner is run in dev mode, and the endpoint is called, I get:

2025-05-27 23:06:03,346 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-1) HTTP Request to /hello failed, error id: 9064607e-6c5e-45a4-83a2-d3b31c105faa-1: java.lang.NoClassDefFoundError: io/leaf/SomeCLass
	at io.blob.Intermediate.someMethod(Intermediate.java:8)
	at io.example.ExampleResource.hello(ExampleResource.java:16)
	at io.example.ExampleResource$quarkusrestinvoker$hello_df324e1539083188359af68039a7afafb7b77cdb.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$15.runWith(VertxCoreRecorder.java:637)
	at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2675)
	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2654)
	at org.jboss.threads.EnhancedQueueExecutor.runThreadBody(EnhancedQueueExecutor.java:1627)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1594)
	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11)
	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.lang.ClassNotFoundException: io.leaf.SomeCLass
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
	at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:576)
	at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:523)
	... 15 more

io.leaf.SomeCLass is located in :project-b.

How to Reproduce?

A minimal reproducer can be found in this public repo: https://github.com/reaver585/quarkus-jar-classloading

To reproduce:

  1. Clone the repo.
  2. ./gradlew --console=plain :runner:quarkusDev
  3. curl -X GET --location "http://localhost:8080/hello"
  4. Observe the exception in the logs.

Output of uname -a or ver

Darwin TW-MBP-M2 24.4.0 Darwin Kernel Version 24.4.0: Fri Apr 11 18:33:39 PDT 2025; root:xnu-11417.101.15~117/RELEASE_ARM64_T6020 arm64

Output of java -version

openjdk version "21.0.7" 2025-04-15 LTS OpenJDK Runtime Environment Temurin-21.0.7+6 (build 21.0.7+6-LTS) OpenJDK 64-Bit Server VM Temurin-21.0.7+6 (build 21.0.7+6-LTS, mixed mode, sharing)

Quarkus version or git rev

3.22.1

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

Gradle 8.13

Additional information

The issue stops manifesting if:

  • I comment out the jar task completely
  • I comment out the archiveClassifier = "something" line in the jar config.

So my hunch is that there is some logic that assigns my classes to the wrong classloader based on the presence of archive classifier for the jar. It causes io.blob.Intermediate class in :project-a to be loaded via base runtime classloader which then cannot see the io.leaf.SomeCLass from :project-b.

If this is indeed a bug, I wouldn't mind help you fix it if you point me in the right direction.

Thanks in advance.

@reaver585 reaver585 added the kind/bug Something isn't working label May 27, 2025
Copy link

quarkus-bot bot commented May 27, 2025

/cc @glefloch, @quarkusio/devtools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/devmode area/gradle Gradle kind/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant