# HG changeset patch # User jjg # Date 1367962050 25200 # Node ID 03f330c02d97adde232caeb0f670e16767e6c767 # Parent 567df13792533665fa5a910bd7842d662e15d207 8004082: test/tools/javac/plugin/showtype/Test.java fails on windows: jtreg can't delete plugin.jar Reviewed-by: vromero, mcimadamore diff -r 567df1379253 -r 03f330c02d97 langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java --- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue May 07 06:39:34 2013 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue May 07 14:27:30 2013 -0700 @@ -1666,6 +1666,7 @@ throw new FatalError(msg, e); } } + closeables = List.nil(); } } diff -r 567df1379253 -r 03f330c02d97 langtools/src/share/classes/com/sun/tools/javac/main/Main.java --- a/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Tue May 07 06:39:34 2013 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Tue May 07 14:27:30 2013 -0700 @@ -35,7 +35,6 @@ import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashSet; -import java.util.ServiceLoader; import java.util.Set; import javax.annotation.processing.Processor; @@ -56,6 +55,7 @@ import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.Log.PrefixKind; import com.sun.tools.javac.util.Log.WriterKind; +import com.sun.tools.javac.util.ServiceLoader; import static com.sun.tools.javac.main.Option.*; /** This class provides a command line interface to the javac compiler. @@ -469,7 +469,6 @@ pluginMessage(ex); return Result.SYSERR; } - } } } diff -r 567df1379253 -r 03f330c02d97 langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java --- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Tue May 07 06:39:34 2013 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Tue May 07 14:27:30 2013 -0700 @@ -76,6 +76,7 @@ import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Names; import com.sun.tools.javac.util.Options; +import com.sun.tools.javac.util.ServiceLoader; import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING; import static com.sun.tools.javac.main.Option.*; import static com.sun.tools.javac.comp.CompileStates.CompileState; @@ -166,6 +167,7 @@ protected JavacProcessingEnvironment(Context context) { this.context = context; + context.put(JavacProcessingEnvironment.class, this); log = Log.instance(context); source = Source.instance(context); diags = JCDiagnostic.Factory.instance(context); diff -r 567df1379253 -r 03f330c02d97 langtools/src/share/classes/com/sun/tools/javac/util/ServiceLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/share/classes/com/sun/tools/javac/util/ServiceLoader.java Tue May 07 14:27:30 2013 -0700 @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.ServiceConfigurationError; + + +/** + * This is a temporary, modified copy of java.util.ServiceLoader, for use by + * javac, to work around bug JDK-8004082. + * + * The bug describes problems in the interaction between ServiceLoader and + * URLClassLoader, such that references to a jar file passed to URLClassLoader + * may be retained after calling URLClassLoader.close(), preventing the jar + * file from being deleted on Windows. + * + *
This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.
+ */
+
+public final class ServiceLoader After invoking this method, subsequent invocations of the {@link
+ * #iterator() iterator} method will lazily look up and instantiate
+ * providers from scratch, just as is done by a newly-created loader.
+ *
+ * This method is intended for use in situations in which new providers
+ * can be installed into a running Java virtual machine.
+ */
+ public void reload() {
+ providers.clear();
+ lookupIterator = new LazyIterator(service, loader);
+ }
+
+ private ServiceLoader(Class The iterator returned by this method first yields all of the
+ * elements of the provider cache, in instantiation order. It then lazily
+ * loads and instantiates any remaining providers, adding each one to the
+ * cache in turn.
+ *
+ * To achieve laziness the actual work of parsing the available
+ * provider-configuration files and instantiating providers must be done by
+ * the iterator itself. Its {@link java.util.Iterator#hasNext hasNext} and
+ * {@link java.util.Iterator#next next} methods can therefore throw a
+ * {@link ServiceConfigurationError} if a provider-configuration file
+ * violates the specified format, or if it names a provider class that
+ * cannot be found and instantiated, or if the result of instantiating the
+ * class is not assignable to the service type, or if any other kind of
+ * exception or error is thrown as the next provider is located and
+ * instantiated. To write robust code it is only necessary to catch {@link
+ * ServiceConfigurationError} when using a service iterator.
+ *
+ * If such an error is thrown then subsequent invocations of the
+ * iterator will make a best effort to locate and instantiate the next
+ * available provider, but in general such recovery cannot be guaranteed.
+ *
+ * The iterator returned by this method does not support removal.
+ * Invoking its {@link java.util.Iterator#remove() remove} method will
+ * cause an {@link UnsupportedOperationException} to be thrown.
+ *
+ * @return An iterator that lazily loads providers for this loader's
+ * service
+ */
+ public Iterator An invocation of this convenience method of the form
+ *
+ * This convenience method simply locates the extension class loader,
+ * call it extClassLoader, and then returns
+ *
+ * If the extension class loader cannot be found then the system class
+ * loader is used; if there is no system class loader then the bootstrap
+ * class loader is used.
+ *
+ * This method is intended for use when only installed providers are
+ * desired. The resulting service will only find and load providers that
+ * have been installed into the current Java virtual machine; providers on
+ * the application's class path will be ignored.
+ *
+ * @param service
+ * The interface or abstract class representing the service
+ *
+ * @return A new service loader
+ */
+ public static
+ implements Iterable
+{
+
+ private static final String PREFIX = "META-INF/services/";
+
+ // The class or interface representing the service being loaded
+ private Class service;
+
+ // The class loader used to locate, load, and instantiate providers
+ private ClassLoader loader;
+
+ // Cached providers, in instantiation order
+ private LinkedHashMap svc, ClassLoader cl) {
+ service = Objects.requireNonNull(svc, "Service interface cannot be null");
+ loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
+ reload();
+ }
+
+ private static void fail(Class> service, String msg, Throwable cause)
+ throws ServiceConfigurationError
+ {
+ throw new ServiceConfigurationError(service.getName() + ": " + msg,
+ cause);
+ }
+
+ private static void fail(Class> service, String msg)
+ throws ServiceConfigurationError
+ {
+ throw new ServiceConfigurationError(service.getName() + ": " + msg);
+ }
+
+ private static void fail(Class> service, URL u, int line, String msg)
+ throws ServiceConfigurationError
+ {
+ fail(service, u + ":" + line + ": " + msg);
+ }
+
+ // Parse a single line from the given configuration file, adding the name
+ // on the line to the names list.
+ //
+ private int parseLine(Class> service, URL u, BufferedReader r, int lc,
+ List
+ {
+
+ Class service;
+ ClassLoader loader;
+ Enumeration service, ClassLoader loader) {
+ this.service = service;
+ this.loader = loader;
+ }
+
+ public boolean hasNext() {
+ if (nextName != null) {
+ return true;
+ }
+ if (configs == null) {
+ try {
+ String fullName = PREFIX + service.getName();
+ if (loader == null)
+ configs = ClassLoader.getSystemResources(fullName);
+ else
+ configs = loader.getResources(fullName);
+ } catch (IOException x) {
+ fail(service, "Error locating configuration files", x);
+ }
+ }
+ while ((pending == null) || !pending.hasNext()) {
+ if (!configs.hasMoreElements()) {
+ return false;
+ }
+ pending = parse(service, configs.nextElement());
+ }
+ nextName = pending.next();
+ return true;
+ }
+
+ public S next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ String cn = nextName;
+ nextName = null;
+ Class> c = null;
+ try {
+ c = Class.forName(cn, false, loader);
+ } catch (ClassNotFoundException x) {
+ fail(service,
+ "Provider " + cn + " not found");
+ }
+ if (!service.isAssignableFrom(c)) {
+ fail(service,
+ "Provider " + cn + " not a subtype");
+ }
+ try {
+ S p = service.cast(c.newInstance());
+ providers.put(cn, p);
+ return p;
+ } catch (Throwable x) {
+ fail(service,
+ "Provider " + cn + " could not be instantiated: " + x,
+ x);
+ }
+ throw new Error(); // This cannot happen
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+ /**
+ * Lazily loads the available providers of this loader's service.
+ *
+ * Design Note
+ * Throwing an error in these cases may seem extreme. The rationale for
+ * this behavior is that a malformed provider-configuration file, like a
+ * malformed class file, indicates a serious problem with the way the Java
+ * virtual machine is configured or is being used. As such it is
+ * preferable to throw an error rather than try to recover or, even worse,
+ * fail silently.
+ *
+ * iterator() {
+ return new Iterator() {
+
+ Iterator ServiceLoader load(Class service,
+ ClassLoader loader)
+ {
+ return new ServiceLoader<>(service, loader);
+ }
+
+ /**
+ * Creates a new service loader for the given service type, using the
+ * current thread's {@linkplain java.lang.Thread#getContextClassLoader
+ * context class loader}.
+ *
+ *
+ *
+ * is equivalent to
+ *
+ *
+ * ServiceLoader.load(service)
+ *
+ * @param service
+ * The interface or abstract class representing the service
+ *
+ * @return A new service loader
+ */
+ public static
+ * ServiceLoader.load(service,
+ * Thread.currentThread().getContextClassLoader())
ServiceLoader load(Class service) {
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ return ServiceLoader.load(service, cl);
+ }
+
+ /**
+ * Creates a new service loader for the given service type, using the
+ * extension class loader.
+ *
+ *
+ *
+ *
+ * ServiceLoader.load(service, extClassLoader)
ServiceLoader loadInstalled(Class service) {
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ ClassLoader prev = null;
+ while (cl != null) {
+ prev = cl;
+ cl = cl.getParent();
+ }
+ return ServiceLoader.load(service, prev);
+ }
+
+ /**
+ * Returns a string describing this service.
+ *
+ * @return A descriptive string
+ */
+ public String toString() {
+ return "java.util.ServiceLoader[" + service.getName() + "]";
+ }
+
+}
diff -r 567df1379253 -r 03f330c02d97 langtools/test/tools/javac/plugin/showtype/Test.java
--- a/langtools/test/tools/javac/plugin/showtype/Test.java Tue May 07 06:39:34 2013 -0700
+++ b/langtools/test/tools/javac/plugin/showtype/Test.java Tue May 07 14:27:30 2013 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 8001098 8004961
+ * @bug 8001098 8004961 8004082
* @summary Provide a simple light-weight "plug-in" mechanism for javac
*/