You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by sc...@apache.org on 2015/11/02 02:29:56 UTC

svn commit: r1711872 - /uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/JCasRegistry.java

Author: schor
Date: Mon Nov  2 01:29:56 2015
New Revision: 1711872

URL: http://svn.apache.org/viewvc?rev=1711872&view=rev
Log:
[UIMA-4666] update registry code to be more efficient

Modified:
    uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/JCasRegistry.java

Modified: uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/JCasRegistry.java
URL: http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/JCasRegistry.java?rev=1711872&r1=1711871&r2=1711872&view=diff
==============================================================================
--- uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/JCasRegistry.java (original)
+++ uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/jcas/JCasRegistry.java Mon Nov  2 01:29:56 2015
@@ -18,6 +18,8 @@
  */
 package org.apache.uima.jcas;
 
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 
 import org.apache.uima.jcas.cas.TOP;
@@ -26,20 +28,53 @@ import org.apache.uima.jcas.cas.TOP;
  * Maintains a registry of JCas cover classes that have been loaded.  Methods on this
  * class are called from JCas cover classes (that is, classes generated by JCasGen).
  * They are not intended to be called directly from user-written code.
+ * 
+ * There are two kinds of JCasr classes: built-in and other.  
+ * JCas "other" classes may have multiple versions for the same named class generated and loaded
+ * under different class loaders;  
+ * 
+ * This supports the use cases of
+ *   - different type systems being used, either
+ *      -- sequentially by a single instance of UIMA or
+ *      -- multiple instances of pipelines running in one JVM each with different type systems 
+ * 
+ * To avoid memory leaks, weak refs are used.
  */
 public class JCasRegistry {
-  private static ArrayList<Class<? extends TOP>> loadedJCasClasses = new ArrayList<>();
+  
+  private static class WeakRefInt<T> extends WeakReference<T> {
+    int index;
+    
+    WeakRefInt(T item, ReferenceQueue<T> q, int index) {
+      super(item, q);
+      this.index = index;
+    }
+  }
+  
+  final private static ArrayList<WeakRefInt<Class<? extends TOP>>> loadedJCasClasses = new ArrayList<>();
+  final private static ReferenceQueue<Class<? extends TOP>> releasedQueue = new ReferenceQueue<>();
   
   /**
    * Registers a JCas cover class with this registry.  The registry will assign
    * it a unique index, which is then used by the cover-class to identify itself
    * to the JCas implementation.
+   * 
+   * Before adding the class to the array list, see if there are any "free" slots in the array list
    * @param aJCasCoverClass the class to register
    * @return the unique index value for this class.
    */
   public static synchronized int register(Class<? extends TOP> aJCasCoverClass) {
-    loadedJCasClasses.add(aJCasCoverClass);
-    return loadedJCasClasses.size() - 1;
+    WeakRefInt<Class<? extends TOP>> releasedWeakRef = (WeakRefInt<Class<? extends TOP>>) releasedQueue.poll();
+    
+    if (releasedWeakRef != null) {
+      int i = ((WeakRefInt<Class<? extends TOP>>)releasedWeakRef).index;
+      loadedJCasClasses.set(i, new WeakRefInt<Class<? extends TOP>>(aJCasCoverClass, releasedQueue, i));
+      return i;
+    }
+     
+    int i = loadedJCasClasses.size();
+    loadedJCasClasses.add(new WeakRefInt<Class<? extends TOP>>(aJCasCoverClass, releasedQueue, i));
+    return i;
   }
   
   /**
@@ -78,7 +113,7 @@ public class JCasRegistry {
    */
   public static synchronized Class<? extends TOP> getClassForIndex(int aIndex) {
     if (aIndex >= 0 && aIndex < loadedJCasClasses.size())
-      return loadedJCasClasses.get(aIndex);
+      return loadedJCasClasses.get(aIndex).get();
     else
       return null;
   }