You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by pe...@apache.org on 2011/06/13 07:36:09 UTC
svn commit: r1135027 -
/river/jtsk/trunk/src/net/jini/loader/pref/PreferredClassProvider.java
Author: peter_firmstone
Date: Mon Jun 13 05:36:09 2011
New Revision: 1135027
URL: http://svn.apache.org/viewvc?rev=1135027&view=rev
Log:
River-396 Christopher Dolan's patch for PreferredClassProvider concurrency
Modified:
river/jtsk/trunk/src/net/jini/loader/pref/PreferredClassProvider.java
Modified: river/jtsk/trunk/src/net/jini/loader/pref/PreferredClassProvider.java
URL: http://svn.apache.org/viewvc/river/jtsk/trunk/src/net/jini/loader/pref/PreferredClassProvider.java?rev=1135027&r1=1135026&r2=1135027&view=diff
==============================================================================
--- river/jtsk/trunk/src/net/jini/loader/pref/PreferredClassProvider.java (original)
+++ river/jtsk/trunk/src/net/jini/loader/pref/PreferredClassProvider.java Mon Jun 13 05:36:09 2011
@@ -43,6 +43,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.WeakHashMap;
@@ -274,7 +276,7 @@ public class PreferredClassProvider exte
* references, so this table does not prevent loaders from being
* garbage collected.
*/
- private final Map loaderTable = new HashMap();
+ private final Map<LoaderKey,LoaderEntryHolder> loaderTable = new HashMap<LoaderKey,LoaderEntryHolder>();
/** reference queue for cleared class loader entries */
private final ReferenceQueue refQueue = new ReferenceQueue();
@@ -1556,31 +1558,55 @@ public class PreferredClassProvider exte
* }
*/
+ /*
+ * Take this opportunity to remove from the table entries
+ * whose weak references have been cleared.
+ */
+ List<LoaderKey> toRemove = new LinkedList<LoaderKey>();
+ Object ref;
+ while ((ref = refQueue.poll()) != null) {
+ if (ref instanceof LoaderKey)
+ toRemove.add((LoaderKey) ref);
+ else if (ref instanceof LoaderEntry) {
+ LoaderEntry entry = (LoaderEntry) ref;
+ if (!entry.removed) // ignore entries removed below
+ toRemove.add(entry.key);
+ }
+ }
+
+ LoaderKey key = new LoaderKey(urls, parent);
+ LoaderEntryHolder holder;
synchronized (loaderTable) {
- /*
- * Take this opportunity to remove from the table entries
- * whose weak references have been cleared.
- */
- Object ref;
- while ((ref = refQueue.poll()) != null) {
- if (ref instanceof LoaderKey) {
- LoaderKey key = (LoaderKey) ref;
- loaderTable.remove(key);
- } else if (ref instanceof LoaderEntry) {
- LoaderEntry entry = (LoaderEntry) ref;
- if (!entry.removed) { // ignore entries removed below
- loaderTable.remove(entry.key);
- }
- }
+ if (!toRemove.isEmpty()) {
+ for (LoaderKey oldKey : toRemove)
+ loaderTable.remove(oldKey);
+ toRemove.clear();
}
/*
* Look up the codebase URL path and parent class loader pair
* in the table of RMI class loaders.
*/
- LoaderKey key = new LoaderKey(urls, parent);
- LoaderEntry entry = (LoaderEntry) loaderTable.get(key);
+ holder = loaderTable.get(key);
+ if (null == holder) {
+ holder = new LoaderEntryHolder();
+ loaderTable.put(key, holder);
+ }
+ }
+ /*
+ * Four possible cases:
+ * 1) this is our first time creating this classloader
+ * - holder.entry is null, need to make a new entry and a new loader
+ * 2) we made this classloader before, but it was garbage collected a long while ago
+ * - identical to case #1 and it was reaped by the toRemove code above
+ * 3) we made this classloader before, and it was garbage collected recently
+ * - holder.entry is non-null, but holder.entry.get() is null, very similar to case #1
+ * 4) we made this classloader before, and it's still alive (CACHE HIT)
+ * - just return it
+ */
+ synchronized (holder) {
+ LoaderEntry entry = holder.entry;
ClassLoader loader;
if (entry == null ||
(loader = (ClassLoader) entry.get()) == null)
@@ -1593,7 +1619,6 @@ public class PreferredClassProvider exte
* from the weak reference queue.
*/
if (entry != null) {
- loaderTable.remove(key);
entry.removed = true;
}
@@ -1623,7 +1648,7 @@ public class PreferredClassProvider exte
* weak reference and store it in the table with the key.
*/
entry = new LoaderEntry(key, loader);
- loaderTable.put(key, entry);
+ holder.entry = entry;
}
return loader;
}
@@ -1737,6 +1762,9 @@ public class PreferredClassProvider exte
this.key = key;
}
}
+ private class LoaderEntryHolder {
+ public LoaderEntry entry;
+ }
private static ClassLoader getClassLoader(final Class c) {
return (ClassLoader) AccessController.doPrivileged(