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

When a Gradle project uses "testImplementation project(path: ':projectname', configuration: 'configurationname')" a Quarkus-vs-JVM class loader conflict appears very late in test execution #27213

Closed
jskillin-idt opened this issue Aug 9, 2022 · 5 comments
Labels
area/gradle Gradle kind/bug Something isn't working

Comments

@jskillin-idt
Copy link
Contributor

jskillin-idt commented Aug 9, 2022

Describe the bug

This was a particularly strange, very nasty-to-debug issue so this one may require some discussion.

First, some background: in a Maven version of a Quarkus project, there was a project structure listed here as "the easy way" to reuse some test code between projects. This influenced the project's transition to Gradle, in which the test sources of one library were wired up to be exported as a JAR under a separate configuration so that another project could depend on them and reuse them.

Gradle itself was perfectly happy with the very simplistic approach and wired up the classpath to test and run correctly.

Quarkus, however, did not appreciate these shenanigans. Very late into the test run, there were quite a lot of class loader errors, and strangely if the dependencies were tweaked, that would seemingly "fix" one error and another would appear.

Expected behavior

Quarkus is able to read the rather niche dependency list and still run.

Actual behavior

Quarkus gives a variety of stack traces fairly late in the test run, such as:

java.lang.LinkageError: loader constraint violation for class org.acme.test.EndToEnd_IT: when selecting overriding method 'org.apache.camel.builder.RouteBuilder org.acme.test.EndToEnd_IT.createRouteBuilder(java.util.Collection, java.util.Collection)' the class loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @4fb392c4 of the selected method's type org.acme.test.EndToEnd_IT, and the class loader 'app' for its super type org.acme.test.AbstractEndToEnd have different Class objects for the type org.apache.camel.builder.RouteBuilder used in the signature (org.acme.test.EndToEnd_IT is in unnamed module of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @4fb392c4, parent loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @3956b302; org.acme.test.AbstractEndToEnd is in unnamed module of loader 'app')

Or, in the reproducer:

java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    org/acme/ExampleTest.afterAll()V @7: invokestatic
  Reason:
    Type 'org/acme/util/SaySomethingTesty' (current frame, stack[0]) is not assignable to 'org/acme/util/SaySomething'
  Current Frame:
    bci: @7
    flags: { }
    locals: { }
    stack: { 'org/acme/util/SaySomethingTesty' }
  Bytecode:
    0000000: bb00 0b59 b700 0cb8 000d b1            

	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:398)
	at io.quarkus.test.junit.QuarkusTestExtension.runExtensionMethod(QuarkusTestExtension.java:987)
	at io.quarkus.test.junit.QuarkusTestExtension.runExtensionMethod(QuarkusTestExtension.java:977)
[snip]

How to Reproduce?

Reproducer: https://github.com/jskillin-idt/quarkusio-quarkus-issues-27213

  1. Clone the reproducer
  2. Run ./gradlew :app:test (the "extra-lib" tests will fail for inconsequential reasons)

For comparison while debugging, I've provided a version of the project which succeeds, under the branch "test-fixtures".

Output of uname -a or ver

Linux jacob-ubuntu-dev 5.15.0-43-generic #46-Ubuntu SMP Tue Jul 12 10:30:17 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

Output of java -version

openjdk version "11.0.16" 2022-07-19 OpenJDK Runtime Environment (build 11.0.16+8-post-Ubuntu-0ubuntu122.04) OpenJDK 64-Bit Server VM (build 11.0.16+8-post-Ubuntu-0ubuntu122.04, mixed mode, sharing)

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.11.2.Final

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

Gradle 7.4.1

Additional information

Gradle is a build tool that has overwhelming flexibility in what it can do, so it's not surprising to me that going off the officially-documented path discovers corner cases in plugins like Quarkus which try to wrap that complexity with their own logic and build instructions.

The particular use case that allowed me to discover this bug is invalid because an official feature called test fixtures codifies exactly what was desired, and Quarkus happens to work just fine if this feature is used instead.

However, in my humble opinion, this bug is still valid as it reveals a corner case in how dependencies are handled, and that corner case might come up again in a more obscure use case.

@jskillin-idt jskillin-idt added the kind/bug Something isn't working label Aug 9, 2022
@quarkus-bot quarkus-bot bot added the area/gradle Gradle label Aug 9, 2022
@quarkus-bot
Copy link

quarkus-bot bot commented Aug 9, 2022

/cc @glefloch, @quarkusio/devtools

@jskillin-idt
Copy link
Contributor Author

Reproducer has been edited in

@jskillin-idt
Copy link
Contributor Author

The reproducer was updated to be far slimmer, since it was built on an old reproducer and in fact was reproducing that bug as well 😆 The latest commits should be good to go.

@jskillin-idt jskillin-idt changed the title When a Gradle project uses "testImplementation project(path: ':projectname', configuration: 'configurationname')" Quarkus ignores the dependency, creating a class loader conflict very late in test execution When a Gradle project uses "testImplementation project(path: ':projectname', configuration: 'configurationname')" a Quarkus-vs-JVM class loader conflict appears very late in test execution Aug 9, 2022
@jskillin-idt
Copy link
Contributor Author

(I updated the title to reflect the issue rather than what I thought was the possible solution.)

@gsmet
Copy link
Member

gsmet commented Aug 22, 2024

I tried to have a look at this one but it took us too long to get to it and I couldn't get the project to work with the latest versions.

Given the OP had it fixed and we didn't hear much complaint about this, I'm going to close this one - even if I'm not sure it's actually solved.

If you encounter a similar issue, please open a new issue with a reproducer.

@gsmet gsmet closed this as not planned Won't fix, can't repro, duplicate, stale Aug 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/gradle Gradle kind/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants