Skip to content

Custom classloader environment exposes GC class/loader leak in ClassByNameCache #1053

@chrisdennis

Description

@chrisdennis

The implementation of ClassByNameCache appears to cause class leaks by failing to properly clean up FutureValue references on the failure path where the loader is not "the system loader". This seems to cause two symptoms:

  1. Singular classes (highly unlikely to be defined multiple times) that are loaded by the either the platform loader, or the bootstrap loader are left in the cache, indirecting through FutureValue instances on every lookup. This is harmless but is probably costing some tiny amount of performance:
Image
  1. Classes loaded by custom class loaders that need to be unloadable cannot be since the ClassByNameCache is strongly referencing one of the loaded classes that has been pulled through serialization.
Image

The trivial fix to 2 is purge the cache key on seeing a "non-system loader" in the update method:

diff --git a/closed/src/java.base/share/classes/java/io/ClassByNameCache.java b/closed/src/java.base/share/classes/java/io/ClassByNameCache.java
index 332caec9675..e8e3801c145 100644
--- a/closed/src/java.base/share/classes/java/io/ClassByNameCache.java
+++ b/closed/src/java.base/share/classes/java/io/ClassByNameCache.java
@@ -116,6 +116,7 @@ void update(CacheKey key, Class<?> result) {
         Object resultLoaderObj =
             LoaderRef.getLoaderObj(result.getClassLoader());
         if (getCanonicalLoaderRef(resultLoaderObj).isSystem == false) {
+            cache.remove(key);
             return;
         }
 

This will have the unfortunate side-effect of negating the performance benefit of the class caching for the bulk of the JDK standard library classes. A complete fix would be to also enhance the loader check to take in to account all three of the "special" loaders: system, platform and bootstrap.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions