src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java

Print this page
rev 378 : 6548708: Annotation processing should free service loader if there are no processors
Reviewed-by: jjg

@@ -285,15 +285,16 @@
      */
     private class ServiceIterator implements Iterator<Processor> {
         // The to-be-wrapped iterator.
         private Iterator<?> iterator;
         private Log log;
+        private Class<?> loaderClass;
+        private boolean jusl;
+        private Object loader;
 
         ServiceIterator(ClassLoader classLoader, Log log) {
-            Class<?> loaderClass;
             String loadMethodName;
-            boolean jusl;
 
             this.log = log;
             try {
                 try {
                     loaderClass = Class.forName("java.util.ServiceLoader");

@@ -322,10 +323,11 @@
                                                   classLoader);
 
                 // For java.util.ServiceLoader, we have to call another
                 // method to get the iterator.
                 if (jusl) {
+                    loader = result; // Store ServiceLoader to call reload later
                     Method m = loaderClass.getMethod("iterator");
                     result = m.invoke(result); // serviceLoader.iterator();
                 }
 
                 // The result should now be an iterator.

@@ -363,10 +365,22 @@
         }
 
         public void remove() {
             throw new UnsupportedOperationException();
         }
+
+        public void close() {
+            if (jusl) {
+                try {
+                    // Call java.util.ServiceLoader.reload
+                    Method reloadMethod = loaderClass.getMethod("reload");
+                    reloadMethod.invoke(loader);
+                } catch(Exception e) {
+                    ; // Ignore problems during a call to reload.
+                }
+            }
+        }
     }
 
 
     private static class NameProcessIterator implements Iterator<Processor> {
         Processor nextProc = null;

@@ -550,11 +564,11 @@
     /**
      * This class holds information about the processors that have
      * been discoverd so far as well as the means to discover more, if
      * necessary.  A single iterator should be used per round of
      * annotation processing.  The iterator first visits already
-     * discovered processors then fails over to the service provided
+     * discovered processors then fails over to the service provider
      * mechanism if additional queries are made.
      */
     class DiscoveredProcessors implements Iterable<ProcessorState> {
 
         class ProcessorStateIterator implements Iterator<ProcessorState> {

@@ -622,10 +636,20 @@
 
         DiscoveredProcessors(Iterator<? extends Processor> processorIterator) {
             this.processorIterator = processorIterator;
             this.procStateList = new ArrayList<ProcessorState>();
         }
+
+        /**
+         * Free jar files, etc. if using a service loader.
+         */
+        public void close() {
+            if (processorIterator != null &&
+                processorIterator instanceof ServiceIterator) {
+                ((ServiceIterator) processorIterator).close();
+            }
+        }
     }
 
     private void discoverAndRunProcs(Context context,
                                      Set<TypeElement> annotationsPresent,
                                      List<ClassSymbol> topLevelClasses,

@@ -1021,10 +1045,12 @@
     /**
      * Free resources related to annotation processing.
      */
     public void close() throws IOException {
         filer.close();
+        if (discoveredProcs != null) // Make calling close idempotent
+            discoveredProcs.close();
         discoveredProcs = null;
         if (processorClassLoader != null && processorClassLoader instanceof Closeable)
             ((Closeable) processorClassLoader).close();
     }