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,299 **** */ private class ServiceIterator implements Iterator<Processor> { // The to-be-wrapped iterator. private Iterator<?> iterator; private Log log; ServiceIterator(ClassLoader classLoader, Log log) { - Class<?> loaderClass; String loadMethodName; - boolean jusl; this.log = log; try { try { loaderClass = Class.forName("java.util.ServiceLoader"); --- 285,300 ---- */ 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) { String loadMethodName; this.log = log; try { try { loaderClass = Class.forName("java.util.ServiceLoader");
*** 322,331 **** --- 323,333 ---- 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,372 **** --- 365,386 ---- } 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,560 **** /** * 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 * mechanism if additional queries are made. */ class DiscoveredProcessors implements Iterable<ProcessorState> { class ProcessorStateIterator implements Iterator<ProcessorState> { --- 564,574 ---- /** * 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 provider * mechanism if additional queries are made. */ class DiscoveredProcessors implements Iterable<ProcessorState> { class ProcessorStateIterator implements Iterator<ProcessorState> {
*** 622,631 **** --- 636,655 ---- 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,1030 **** --- 1045,1056 ---- /** * 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(); }