Skip to content

Commit

Permalink
Improve type resolution cache for classes in java package (#7714)
Browse files Browse the repository at this point in the history
Classes in `java.` package can only be loaded by boot loader. As the
class loader that we currently use in cache key for these classes isn't
always the boot loader we can end up with multiple entries for the same
class.
  • Loading branch information
laurit authored Feb 3, 2023
1 parent 0bd4af0 commit 8d74cf1
Showing 1 changed file with 14 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ private TypePool.CacheProvider getCacheProvider(ClassLoader classLoader) {
WeakReference<ClassLoader> loaderRef =
loaderRefCache.computeIfAbsent(classLoader, WeakReference::new);

int loaderHash = classLoader.hashCode();
int loaderHash = System.identityHashCode(classLoader);
return new SharedResolutionCacheAdapter(loaderHash, loaderRef, sharedResolutionCache);
}

Expand All @@ -168,17 +168,19 @@ private TypePool.CacheProvider getCacheProvider(ClassLoader classLoader) {
*/
private static final class TypeCacheKey {
private final int loaderHash;
private final WeakReference<ClassLoader> loaderRef;
@Nullable private final WeakReference<ClassLoader> loaderRef;
private final String className;

private final int hashCode;

TypeCacheKey(int loaderHash, WeakReference<ClassLoader> loaderRef, String className) {
this.loaderHash = loaderHash;
this.loaderRef = loaderRef;
// classes in java package are always loaded from boot loader
// set loader to boot loader to avoid creating multiple cache entries
this.loaderHash = className.startsWith("java.") ? BOOTSTRAP_HASH : loaderHash;
this.loaderRef = className.startsWith("java.") ? null : loaderRef;
this.className = className;

hashCode = 31 * loaderHash + className.hashCode();
hashCode = 31 * this.loaderHash + className.hashCode();
}

@Override
Expand All @@ -204,6 +206,8 @@ public boolean equals(@Nullable Object obj) {
// Also covers the bootstrap null loaderRef case
if (loaderRef == other.loaderRef) {
return true;
} else if (loaderRef == null || other.loaderRef == null) {
return false;
}

// need to perform a deeper loader check -- requires calling Reference.get
Expand Down Expand Up @@ -268,16 +272,16 @@ private static final class SharedResolutionCacheAdapter implements TypePool.Cach

@Override
public TypePool.Resolution find(String className) {
if (OBJECT_NAME.equals(className)) {
return OBJECT_RESOLUTION;
}

TypePool.Resolution existingResolution =
sharedResolutionCache.get(new TypeCacheKey(loaderHash, loaderRef, className));
if (existingResolution != null) {
return existingResolution;
}

if (OBJECT_NAME.equals(className)) {
return OBJECT_RESOLUTION;
}

return null;
}

Expand Down Expand Up @@ -666,7 +670,7 @@ public String getName() {
@Override
public boolean isAnnotation() {
// by default byte-buddy checks whether class modifiers have annotation bit set
// as we wish to avoid looking up the class bytes we assume that every that was expected
// as we wish to avoid looking up the class bytes we assume that every class that was expected
// to be an annotation really is an annotation and return true here
// See TypePool.Default.LazyTypeDescription.LazyAnnotationDescription.asList()
return true;
Expand Down

0 comments on commit 8d74cf1

Please sign in to comment.