You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2017/12/08 13:56:22 UTC
groovy git commit: Achieve fine-grained concurrent access to
classCache
Repository: groovy
Updated Branches:
refs/heads/master 384ee1c44 -> 8815f3ea0
Achieve fine-grained concurrent access to classCache
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/8815f3ea
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/8815f3ea
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/8815f3ea
Branch: refs/heads/master
Commit: 8815f3ea028e0dee13ee319c584613daa7c8947b
Parents: 384ee1c
Author: sunlan <su...@apache.org>
Authored: Fri Dec 8 21:56:06 2017 +0800
Committer: sunlan <su...@apache.org>
Committed: Fri Dec 8 21:56:06 2017 +0800
----------------------------------------------------------------------
src/main/groovy/lang/GroovyClassLoader.java | 54 ++++++++++++++++++------
1 file changed, 41 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/8815f3ea/src/main/groovy/lang/GroovyClassLoader.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/GroovyClassLoader.java b/src/main/groovy/lang/GroovyClassLoader.java
index af01538..7333129 100644
--- a/src/main/groovy/lang/GroovyClassLoader.java
+++ b/src/main/groovy/lang/GroovyClassLoader.java
@@ -72,6 +72,7 @@ import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* A ClassLoader which can load Groovy classes. The loaded classes are cached,
@@ -89,13 +90,17 @@ import java.util.Map;
* @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
*/
public class GroovyClassLoader extends URLClassLoader {
-
private static final URL[] EMPTY_URL_ARRAY = new URL[0];
+ private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
/**
* this cache contains the loaded classes or PARSING, if the class is currently parsed
*/
- protected final Map<String, Class> classCache = new HashMap<String, Class>();
+ protected final Map<String, Class> classCache = new HashMap<String, Class>(); // TODO should we make classCache private?
+
+ private final ReentrantReadWriteLock rwlForClassCache = new ReentrantReadWriteLock();
+ private final ReentrantReadWriteLock.ReadLock readLockForClassCache = rwlForClassCache.readLock();
+ private final ReentrantReadWriteLock.WriteLock writeLockForClassCache = rwlForClassCache.writeLock();
/**
* This cache contains mappings of file name to class. It is used
@@ -614,8 +619,12 @@ public class GroovyClassLoader extends URLClassLoader {
*/
protected Class getClassCacheEntry(String name) {
if (name == null) return null;
- synchronized (classCache) {
+
+ readLockForClassCache.lock();
+ try {
return classCache.get(name);
+ } finally {
+ readLockForClassCache.unlock();
}
}
@@ -628,8 +637,13 @@ public class GroovyClassLoader extends URLClassLoader {
* @see #clearCache()
*/
protected void setClassCacheEntry(Class cls) {
- synchronized (classCache) {
- classCache.put(cls.getName(), cls);
+ String className = cls.getName();
+
+ writeLockForClassCache.lock();
+ try {
+ classCache.put(className, cls);
+ } finally {
+ writeLockForClassCache.unlock();
}
}
@@ -642,8 +656,11 @@ public class GroovyClassLoader extends URLClassLoader {
* @see #clearCache()
*/
protected void removeClassCacheEntry(String name) {
- synchronized (classCache) {
+ writeLockForClassCache.lock();
+ try {
classCache.remove(name);
+ } finally {
+ writeLockForClassCache.unlock();
}
}
@@ -1010,10 +1027,16 @@ public class GroovyClassLoader extends URLClassLoader {
* @return all classes loaded by this class loader
*/
public Class[] getLoadedClasses() {
- synchronized (classCache) {
- final Collection<Class> values = classCache.values();
- return values.toArray(new Class[values.size()]);
+ final Collection<Class> values;
+
+ readLockForClassCache.lock();
+ try {
+ values = classCache.values();
+ } finally {
+ readLockForClassCache.unlock();
}
+
+ return values.toArray(EMPTY_CLASS_ARRAY);
}
/**
@@ -1028,15 +1051,20 @@ public class GroovyClassLoader extends URLClassLoader {
* @see #removeClassCacheEntry(String)
*/
public void clearCache() {
- Class<?>[] clearedClasses;
- synchronized (classCache) {
- clearedClasses = getLoadedClasses();
+ Collection<Class> classesToClear;
+
+ writeLockForClassCache.lock();
+ try {
+ classesToClear = classCache.values();
classCache.clear();
+ } finally {
+ writeLockForClassCache.unlock();
}
+
synchronized (sourceCache) {
sourceCache.clear();
}
- for (Class<?> c : clearedClasses) {
+ for (Class c : classesToClear) {
// Another Thread may be using an instance of this class
// (for the first time) requiring a ClassInfo lock and
// classloading which would require a lock on classCache.