6548708: Annotation processing should free service loader if there are no processors
authordarcy
Wed, 26 Aug 2009 19:28:51 -0700
changeset 3764 f0077f165983
parent 3763 be9e8bdd7ead
child 3765 9548183897cb
6548708: Annotation processing should free service loader if there are no processors Reviewed-by: jjg
langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Tue Aug 25 16:41:32 2009 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Wed Aug 26 19:28:51 2009 -0700
@@ -287,11 +287,12 @@
         // 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 {
@@ -324,6 +325,7 @@
                 // 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();
                 }
@@ -365,6 +367,18 @@
         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.
+                }
+            }
+        }
     }
 
 
@@ -552,7 +566,7 @@
      * 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> {
@@ -624,6 +638,16 @@
             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,
@@ -910,7 +934,7 @@
         * second to last round; errorRaised() gives the error status
         * of the last round.
         */
-       errorStatus = errorStatus || messager.errorRaised();
+        errorStatus = errorStatus || messager.errorRaised();
 
 
         // Free resources
@@ -1023,6 +1047,8 @@
      */
     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();