From 12e05870754bb9cba88a40bc21e988ac0608d2aa Mon Sep 17 00:00:00 2001 From: John Wagenleitner Date: Mon, 19 Sep 2016 11:48:19 -0700 Subject: [PATCH] Compatibility with Gradle's classloader cleanup Gradle has a cleanup mechanism in place that reflectively accesses the ClassInfo.klazz field. This change prevents an exception being thrown by the cleanup method. This workaround also means that the cleanup strategy will no longer work, but the fix to replace klazz with a WeakReference should eliminate the need for the explicit cleanup. For more details, see dev mailing list thread: https://mail-archives.apache.org/mod_mbox/incubator-groovy-dev/201609.mbox/%3CCAHPL-JkQ%2BU8PfaxyVhtE%3DvGV%2BsXXmCzxOsCR8UbBww6P2vskPg%40mail.gmail.com%3E --- .../codehaus/groovy/reflection/ClassInfo.java | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/main/org/codehaus/groovy/reflection/ClassInfo.java b/src/main/org/codehaus/groovy/reflection/ClassInfo.java index 221b905f1c2..542c8e4150c 100644 --- a/src/main/org/codehaus/groovy/reflection/ClassInfo.java +++ b/src/main/org/codehaus/groovy/reflection/ClassInfo.java @@ -49,7 +49,19 @@ public class ClassInfo implements Finalizable { private final LazyClassLoaderRef artifactClassLoader; private final LockableObject lock = new LockableObject(); public final int hash = -1; - private final WeakReference> klazz; + private final WeakReference> classRef; + + // TODO: should be able to remove the klazz field once 2.5 becomes the mainline release + // Gradle has a cleanup mechanism in place to reflectively access this klazz field. + // The klazz field is being kept for compatibility so as to not break builds that depend + // on versions of Groovy after the field was changed to a WeakReference (classRef). It + // appears that Gradle only performs the cleanup when it detects a groovy version of 2.4.x, + // so the klazz field and placeholder Sentinel class can likely be safely removed once + // the release version bumps to 2.5 (or beyond). + // See: + // https://github.com/gradle/gradle/blob/711f64/subprojects/core/src/main/java/org/gradle/api/internal/classloading/LeakyOnJava7GroovySystemLoader.java#L74 + private static final class Sentinel {} + private static final Class klazz = Sentinel.class; private final AtomicInteger version = new AtomicInteger(); @@ -76,7 +88,7 @@ public ClassInfo computeValue(Class type) { private static final GlobalClassSet globalClassSet = new GlobalClassSet(); ClassInfo(Class klazz) { - this.klazz = new WeakReference>(klazz); + this.classRef = new WeakReference>(klazz); cachedClassRef = new LazyCachedClassRef(softBundle, this); artifactClassLoader = new LazyClassLoaderRef(softBundle, this); } @@ -117,7 +129,7 @@ public static void clearModifiedExpandos() { * @return the {@code Class} associated with this {@code ClassInfo}, else {@code null} */ public final Class getTheClass() { - return klazz.get(); + return classRef.get(); } public CachedClass getCachedClass() { @@ -239,7 +251,7 @@ private MetaClass getMetaClassUnderLock() { return answer; } - answer = mccHandle.create(klazz.get(), metaClassRegistry); + answer = mccHandle.create(classRef.get(), metaClassRegistry); answer.initialize(); if (GroovySystem.isKeepJavaMetaClasses()) { @@ -403,7 +415,7 @@ private static class LazyCachedClassRef extends LazyReference { } public CachedClass initValue() { - return createCachedClass(info.klazz.get(), info); + return createCachedClass(info.classRef.get(), info); } } @@ -416,7 +428,7 @@ private static class LazyClassLoaderRef extends LazyReference