LuciferYang opened a new pull request, #12124: URL: https://github.com/apache/gravitino/pull/12124
### What changes were proposed in this pull request? Two additions to `ClassLoaderResourceCleanerUtils.closeClassLoaderResource`: - Shut down MySQL's `AbandonedConnectionCleanupThread` via `uncheckedShutdown()`, which also clears the tracked-connection map so the driver's ClassLoader can be collected. The call is guarded by `isOwnedByClassLoader`, matching the other cleanup steps in this class, so it never stops a cleanup thread owned by a parent or shared ClassLoader (for example a MySQL entity store loaded on the app ClassLoader, whose driver class delegates up to the app loader). - Broaden the ThreadLocal sweep from `Gravitino-webserver-*` threads to all application threads, skipping only the JVM `system` thread group. Only entries whose value was loaded by the target ClassLoader are cleared, so ThreadLocals owned by other ClassLoaders are left alone. ### Why are the changes needed? After a MySQL-backed catalog is dropped, its isolated ClassLoader stays reachable through the `mysql-cj-abandoned-connection-cleanup` thread's context ClassLoader and through ThreadLocals on non-webserver threads (Caffeine ForkJoinPool, catalog-cleaner, Hadoop daemons). `closeClassLoaderResource` releases neither today, so the ClassLoader leaks on every reload and Metaspace grows until `OutOfMemoryError: Metaspace`. Fix: #12123 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Added `TestClassLoaderResourceCleanerUtils` cases (`mysql-connector-j` added as a test-only dependency): - `testShutdownMySQLAbandonedConnectionCleanupThreadStopsThread`: loading `AbandonedConnectionCleanupThread` in a child `URLClassLoader` starts the cleanup thread bound to that loader; after `shutdownMySQLAbandonedConnectionCleanupThread` the thread is gone. It loads the cleanup-thread class directly rather than the driver, so the test does not register a driver into the JVM-global `DriverManager`. - `testShutdownMySQLAbandonedConnectionCleanupThreadSkipsParentOwnedClass`: when the class resolves to a parent loader, a child-scoped cleanup leaves the parent's thread alive; an owner-scoped cleanup stops it. - `testClearThreadLocalMapClearsOnlyTargetClassLoaderValues`: on a non-webserver thread, a ThreadLocal whose value is loaded by the target ClassLoader is cleared, while one loaded by a different (non-null) ClassLoader is kept. - `testClearThreadLocalMapSkipsSystemThreadGroup`: a ThreadLocal on a `system`-group thread is left untouched. Ran `./gradlew :catalogs:catalog-common:test --tests "org.apache.gravitino.utils.TestClassLoaderResourceCleanerUtils"`: 7/7 green. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
