6548708: Annotation processing should free service loader if there are no processors
Reviewed-by: jjg
--- 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();