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

Attempt to alleviate QuarkusClassLoader leaks #41172

Closed
wants to merge 13 commits into from
Closed

Conversation

gsmet
Copy link
Member

@gsmet gsmet commented Jun 12, 2024

This won't fix the leaks as there are multiple reasons why CLs are leaking in tests and dev mode but... I thought we should consider at least reducing the consequences of the leaks by clearing the resources and making sure that the ZipFileSystem can be garbage collected, together with some other elements.

Now there's something a bit odd, if I set state to null, I have a very weird error:

Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.LinkageError: loader constraint violation: loader 'app' wants to load interface io.netty.util.internal.shaded.org.jctools.queues.IndexedQueueSizeUtil$IndexedQueue. A different interface with the same name was previously loaded by io.quarkus.bootstrap.classloading.QuarkusClassLoader @7c4921f1. (io.netty.util.internal.shaded.org.jctools.queues.IndexedQueueSizeUtil$IndexedQueue is in unnamed module of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @7c4921f1, parent loader 'app') [in thread "build-36"]

Which means that somehow the closed class loader is still in use - which is extremely weird... If someone has an idea, I'm interested.

Commit messages have a bit more details.

Related to #41158 and #41156 .

@quarkus-bot quarkus-bot bot added the area/devtools Issues/PR related to maven, gradle, platform and cli tooling/plugins label Jun 12, 2024
@gsmet gsmet marked this pull request as draft June 12, 2024 18:18

This comment has been minimized.

@geoand
Copy link
Contributor

geoand commented Jun 13, 2024

Do you have a stacktrace for that bizarre exception? Never mind, I see it's in the commit message

gsmet added 13 commits June 17, 2024 19:07
- The TestResourceManager is instantiated using the runtime class loader
  so we need to make sure we close it before we close the runtime class
  loader. Otherwise we can get into trouble if we need to load some
  additional classes.
- Also make sure that it is only closed once. It used to be closed once
  when the application is stopped and then again when the
  QuarkusTestExtensionState was closed.
We know that the class loaders can leak, for instance due to long lived
resources that span the boundaries of a test so we try to limit the
effects by clearing the fields from the class loader and especially all
the ClassPathElements.

Note that for now, I didn't nullify the parent field that points to the
parent CL but I wonder if we should do it.
When closing a ZipFileSystem, there is a non trivial amount of data that
is still kept around and in particular the cen field.
Not entirely sure we will keep it but let's run the test suite with it.
Currently, we pass the CL to something that will close it, rather than
controlling the lifecycle in the creator method.

This is an issue in native ITs:

java.lang.RuntimeException: java.lang.IllegalStateException: This class loader has been closed
	at io.quarkus.test.junit.QuarkusIntegrationTestExtension.throwBootFailureException(QuarkusIntegrationTestExtension.java:373)
	at io.quarkus.test.junit.QuarkusIntegrationTestExtension.beforeEach(QuarkusIntegrationTestExtension.java:117)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: java.lang.IllegalStateException: This class loader has been closed
	at io.quarkus.bootstrap.classloading.QuarkusClassLoader.ensureOpen(QuarkusClassLoader.java:716)
	at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:495)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:467)
	at io.quarkus.runner.bootstrap.AugmentActionImpl.performCustomBuild(AugmentActionImpl.java:158)
	at io.quarkus.test.junit.IntegrationTestUtil.handleDevServices(IntegrationTestUtil.java:297)
	at io.quarkus.test.junit.QuarkusIntegrationTestExtension.doProcessStart(QuarkusIntegrationTestExtension.java:199)
	at io.quarkus.test.junit.QuarkusIntegrationTestExtension.ensureStarted(QuarkusIntegrationTestExtension.java:169)
	at io.quarkus.test.junit.QuarkusIntegrationTestExtension.beforeAll(QuarkusIntegrationTestExtension.java:130)
The Augmentation CL is the parent of the deployment CL, so the
deployment CL must be closed first.
This is consistent with what happens when we don't do it manually.
That way, it's easier to differentiate the CL, their lifecycle and what
they are used for.
And also avoid passing the CuratedApplication here.
The problem was noticed when trying to log something in the
QuarkusClassLoader constructor.
When popping provider factory, what we actually want is pop it if
something has been pushed.
It is better handled by setting a boolean if something has been pushed.

This allows class loading issues when the class loader has been closed
and the request is still processing.
There's no real need here and it tries to load classes after the CL has
been closed.
@gsmet
Copy link
Member Author

gsmet commented Jul 2, 2024

I have extracted all the work done here (and more!) in small PRs.
I created the last one today. Once everything is in, the situation should be a lot better.

@gsmet gsmet closed this Jul 2, 2024
@quarkus-bot quarkus-bot bot added the triage/invalid This doesn't seem right label Jul 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/core area/devtools Issues/PR related to maven, gradle, platform and cli tooling/plugins area/jbang Issues related to when using jbang.dev with Quarkus area/maven area/rest area/resteasy-classic area/testing triage/flaky-test triage/invalid This doesn't seem right
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants