Tue, 07 May 2013 14:27:30 -0700
8004082: test/tools/javac/plugin/showtype/Test.java fails on windows: jtreg can't delete plugin.jar
Reviewed-by: vromero, mcimadamore
1.1 --- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue May 07 06:39:34 2013 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue May 07 14:27:30 2013 -0700 1.3 @@ -1666,6 +1666,7 @@ 1.4 throw new FatalError(msg, e); 1.5 } 1.6 } 1.7 + closeables = List.nil(); 1.8 } 1.9 } 1.10
2.1 --- a/src/share/classes/com/sun/tools/javac/main/Main.java Tue May 07 06:39:34 2013 -0700 2.2 +++ b/src/share/classes/com/sun/tools/javac/main/Main.java Tue May 07 14:27:30 2013 -0700 2.3 @@ -35,7 +35,6 @@ 2.4 import java.util.Collection; 2.5 import java.util.Iterator; 2.6 import java.util.LinkedHashSet; 2.7 -import java.util.ServiceLoader; 2.8 import java.util.Set; 2.9 2.10 import javax.annotation.processing.Processor; 2.11 @@ -56,6 +55,7 @@ 2.12 import com.sun.tools.javac.util.*; 2.13 import com.sun.tools.javac.util.Log.PrefixKind; 2.14 import com.sun.tools.javac.util.Log.WriterKind; 2.15 +import com.sun.tools.javac.util.ServiceLoader; 2.16 import static com.sun.tools.javac.main.Option.*; 2.17 2.18 /** This class provides a command line interface to the javac compiler. 2.19 @@ -469,7 +469,6 @@ 2.20 pluginMessage(ex); 2.21 return Result.SYSERR; 2.22 } 2.23 - 2.24 } 2.25 } 2.26 }
3.1 --- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Tue May 07 06:39:34 2013 -0700 3.2 +++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Tue May 07 14:27:30 2013 -0700 3.3 @@ -76,6 +76,7 @@ 3.4 import com.sun.tools.javac.util.Name; 3.5 import com.sun.tools.javac.util.Names; 3.6 import com.sun.tools.javac.util.Options; 3.7 +import com.sun.tools.javac.util.ServiceLoader; 3.8 import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING; 3.9 import static com.sun.tools.javac.main.Option.*; 3.10 import static com.sun.tools.javac.comp.CompileStates.CompileState; 3.11 @@ -166,6 +167,7 @@ 3.12 3.13 protected JavacProcessingEnvironment(Context context) { 3.14 this.context = context; 3.15 + context.put(JavacProcessingEnvironment.class, this); 3.16 log = Log.instance(context); 3.17 source = Source.instance(context); 3.18 diags = JCDiagnostic.Factory.instance(context);
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/share/classes/com/sun/tools/javac/util/ServiceLoader.java Tue May 07 14:27:30 2013 -0700 4.3 @@ -0,0 +1,437 @@ 4.4 +/* 4.5 + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. Oracle designates this 4.11 + * particular file as subject to the "Classpath" exception as provided 4.12 + * by Oracle in the LICENSE file that accompanied this code. 4.13 + * 4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.17 + * version 2 for more details (a copy is included in the LICENSE file that 4.18 + * accompanied this code). 4.19 + * 4.20 + * You should have received a copy of the GNU General Public License version 4.21 + * 2 along with this work; if not, write to the Free Software Foundation, 4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.23 + * 4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.25 + * or visit www.oracle.com if you need additional information or have any 4.26 + * questions. 4.27 + */ 4.28 + 4.29 +package com.sun.tools.javac.util; 4.30 + 4.31 +import java.io.BufferedReader; 4.32 +import java.io.IOException; 4.33 +import java.io.InputStream; 4.34 +import java.io.InputStreamReader; 4.35 +import java.net.URL; 4.36 +import java.net.URLConnection; 4.37 +import java.util.ArrayList; 4.38 +import java.util.Enumeration; 4.39 +import java.util.Iterator; 4.40 +import java.util.LinkedHashMap; 4.41 +import java.util.List; 4.42 +import java.util.Map; 4.43 +import java.util.NoSuchElementException; 4.44 +import java.util.Objects; 4.45 +import java.util.ServiceConfigurationError; 4.46 + 4.47 + 4.48 +/** 4.49 + * This is a temporary, modified copy of java.util.ServiceLoader, for use by 4.50 + * javac, to work around bug JDK-8004082. 4.51 + * 4.52 + * The bug describes problems in the interaction between ServiceLoader and 4.53 + * URLClassLoader, such that references to a jar file passed to URLClassLoader 4.54 + * may be retained after calling URLClassLoader.close(), preventing the jar 4.55 + * file from being deleted on Windows. 4.56 + * 4.57 + * <p><b>This is NOT part of any supported API. 4.58 + * If you write code that depends on this, you do so at your own risk. 4.59 + * This code and its internal interfaces are subject to change or 4.60 + * deletion without notice.</b> 4.61 + */ 4.62 + 4.63 +public final class ServiceLoader<S> 4.64 + implements Iterable<S> 4.65 +{ 4.66 + 4.67 + private static final String PREFIX = "META-INF/services/"; 4.68 + 4.69 + // The class or interface representing the service being loaded 4.70 + private Class<S> service; 4.71 + 4.72 + // The class loader used to locate, load, and instantiate providers 4.73 + private ClassLoader loader; 4.74 + 4.75 + // Cached providers, in instantiation order 4.76 + private LinkedHashMap<String,S> providers = new LinkedHashMap<>(); 4.77 + 4.78 + // The current lazy-lookup iterator 4.79 + private LazyIterator lookupIterator; 4.80 + 4.81 + /** 4.82 + * Clear this loader's provider cache so that all providers will be 4.83 + * reloaded. 4.84 + * 4.85 + * <p> After invoking this method, subsequent invocations of the {@link 4.86 + * #iterator() iterator} method will lazily look up and instantiate 4.87 + * providers from scratch, just as is done by a newly-created loader. 4.88 + * 4.89 + * <p> This method is intended for use in situations in which new providers 4.90 + * can be installed into a running Java virtual machine. 4.91 + */ 4.92 + public void reload() { 4.93 + providers.clear(); 4.94 + lookupIterator = new LazyIterator(service, loader); 4.95 + } 4.96 + 4.97 + private ServiceLoader(Class<S> svc, ClassLoader cl) { 4.98 + service = Objects.requireNonNull(svc, "Service interface cannot be null"); 4.99 + loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl; 4.100 + reload(); 4.101 + } 4.102 + 4.103 + private static void fail(Class<?> service, String msg, Throwable cause) 4.104 + throws ServiceConfigurationError 4.105 + { 4.106 + throw new ServiceConfigurationError(service.getName() + ": " + msg, 4.107 + cause); 4.108 + } 4.109 + 4.110 + private static void fail(Class<?> service, String msg) 4.111 + throws ServiceConfigurationError 4.112 + { 4.113 + throw new ServiceConfigurationError(service.getName() + ": " + msg); 4.114 + } 4.115 + 4.116 + private static void fail(Class<?> service, URL u, int line, String msg) 4.117 + throws ServiceConfigurationError 4.118 + { 4.119 + fail(service, u + ":" + line + ": " + msg); 4.120 + } 4.121 + 4.122 + // Parse a single line from the given configuration file, adding the name 4.123 + // on the line to the names list. 4.124 + // 4.125 + private int parseLine(Class<?> service, URL u, BufferedReader r, int lc, 4.126 + List<String> names) 4.127 + throws IOException, ServiceConfigurationError 4.128 + { 4.129 + String ln = r.readLine(); 4.130 + if (ln == null) { 4.131 + return -1; 4.132 + } 4.133 + int ci = ln.indexOf('#'); 4.134 + if (ci >= 0) ln = ln.substring(0, ci); 4.135 + ln = ln.trim(); 4.136 + int n = ln.length(); 4.137 + if (n != 0) { 4.138 + if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0)) 4.139 + fail(service, u, lc, "Illegal configuration-file syntax"); 4.140 + int cp = ln.codePointAt(0); 4.141 + if (!Character.isJavaIdentifierStart(cp)) 4.142 + fail(service, u, lc, "Illegal provider-class name: " + ln); 4.143 + for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) { 4.144 + cp = ln.codePointAt(i); 4.145 + if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) 4.146 + fail(service, u, lc, "Illegal provider-class name: " + ln); 4.147 + } 4.148 + if (!providers.containsKey(ln) && !names.contains(ln)) 4.149 + names.add(ln); 4.150 + } 4.151 + return lc + 1; 4.152 + } 4.153 + 4.154 + // Parse the content of the given URL as a provider-configuration file. 4.155 + // 4.156 + // @param service 4.157 + // The service type for which providers are being sought; 4.158 + // used to construct error detail strings 4.159 + // 4.160 + // @param u 4.161 + // The URL naming the configuration file to be parsed 4.162 + // 4.163 + // @return A (possibly empty) iterator that will yield the provider-class 4.164 + // names in the given configuration file that are not yet members 4.165 + // of the returned set 4.166 + // 4.167 + // @throws ServiceConfigurationError 4.168 + // If an I/O error occurs while reading from the given URL, or 4.169 + // if a configuration-file format error is detected 4.170 + // 4.171 + private Iterator<String> parse(Class<?> service, URL u) 4.172 + throws ServiceConfigurationError 4.173 + { 4.174 + InputStream in = null; 4.175 + BufferedReader r = null; 4.176 + ArrayList<String> names = new ArrayList<>(); 4.177 + try { 4.178 + // The problem is that by default, streams opened with 4.179 + // u.openInputStream use a cached reference to a JarFile, which 4.180 + // is separate from the reference used by URLClassLoader, and 4.181 + // which is not closed by URLClassLoader.close(). 4.182 + // The workaround is to disable caching for this specific jar file, 4.183 + // so that the reference to the jar file can be closed when the 4.184 + // file has been read. 4.185 + // Original code: 4.186 + // in = u.openStream(); 4.187 + // Workaround ... 4.188 + URLConnection uc = u.openConnection(); 4.189 + uc.setUseCaches(false); 4.190 + in = uc.getInputStream(); 4.191 + // ... end of workaround. 4.192 + r = new BufferedReader(new InputStreamReader(in, "utf-8")); 4.193 + int lc = 1; 4.194 + while ((lc = parseLine(service, u, r, lc, names)) >= 0); 4.195 + } catch (IOException x) { 4.196 + fail(service, "Error reading configuration file", x); 4.197 + } finally { 4.198 + try { 4.199 + if (r != null) r.close(); 4.200 + if (in != null) in.close(); 4.201 + } catch (IOException y) { 4.202 + fail(service, "Error closing configuration file", y); 4.203 + } 4.204 + } 4.205 + return names.iterator(); 4.206 + } 4.207 + 4.208 + // Private inner class implementing fully-lazy provider lookup 4.209 + // 4.210 + private class LazyIterator 4.211 + implements Iterator<S> 4.212 + { 4.213 + 4.214 + Class<S> service; 4.215 + ClassLoader loader; 4.216 + Enumeration<URL> configs = null; 4.217 + Iterator<String> pending = null; 4.218 + String nextName = null; 4.219 + 4.220 + private LazyIterator(Class<S> service, ClassLoader loader) { 4.221 + this.service = service; 4.222 + this.loader = loader; 4.223 + } 4.224 + 4.225 + public boolean hasNext() { 4.226 + if (nextName != null) { 4.227 + return true; 4.228 + } 4.229 + if (configs == null) { 4.230 + try { 4.231 + String fullName = PREFIX + service.getName(); 4.232 + if (loader == null) 4.233 + configs = ClassLoader.getSystemResources(fullName); 4.234 + else 4.235 + configs = loader.getResources(fullName); 4.236 + } catch (IOException x) { 4.237 + fail(service, "Error locating configuration files", x); 4.238 + } 4.239 + } 4.240 + while ((pending == null) || !pending.hasNext()) { 4.241 + if (!configs.hasMoreElements()) { 4.242 + return false; 4.243 + } 4.244 + pending = parse(service, configs.nextElement()); 4.245 + } 4.246 + nextName = pending.next(); 4.247 + return true; 4.248 + } 4.249 + 4.250 + public S next() { 4.251 + if (!hasNext()) { 4.252 + throw new NoSuchElementException(); 4.253 + } 4.254 + String cn = nextName; 4.255 + nextName = null; 4.256 + Class<?> c = null; 4.257 + try { 4.258 + c = Class.forName(cn, false, loader); 4.259 + } catch (ClassNotFoundException x) { 4.260 + fail(service, 4.261 + "Provider " + cn + " not found"); 4.262 + } 4.263 + if (!service.isAssignableFrom(c)) { 4.264 + fail(service, 4.265 + "Provider " + cn + " not a subtype"); 4.266 + } 4.267 + try { 4.268 + S p = service.cast(c.newInstance()); 4.269 + providers.put(cn, p); 4.270 + return p; 4.271 + } catch (Throwable x) { 4.272 + fail(service, 4.273 + "Provider " + cn + " could not be instantiated: " + x, 4.274 + x); 4.275 + } 4.276 + throw new Error(); // This cannot happen 4.277 + } 4.278 + 4.279 + public void remove() { 4.280 + throw new UnsupportedOperationException(); 4.281 + } 4.282 + 4.283 + } 4.284 + 4.285 + /** 4.286 + * Lazily loads the available providers of this loader's service. 4.287 + * 4.288 + * <p> The iterator returned by this method first yields all of the 4.289 + * elements of the provider cache, in instantiation order. It then lazily 4.290 + * loads and instantiates any remaining providers, adding each one to the 4.291 + * cache in turn. 4.292 + * 4.293 + * <p> To achieve laziness the actual work of parsing the available 4.294 + * provider-configuration files and instantiating providers must be done by 4.295 + * the iterator itself. Its {@link java.util.Iterator#hasNext hasNext} and 4.296 + * {@link java.util.Iterator#next next} methods can therefore throw a 4.297 + * {@link ServiceConfigurationError} if a provider-configuration file 4.298 + * violates the specified format, or if it names a provider class that 4.299 + * cannot be found and instantiated, or if the result of instantiating the 4.300 + * class is not assignable to the service type, or if any other kind of 4.301 + * exception or error is thrown as the next provider is located and 4.302 + * instantiated. To write robust code it is only necessary to catch {@link 4.303 + * ServiceConfigurationError} when using a service iterator. 4.304 + * 4.305 + * <p> If such an error is thrown then subsequent invocations of the 4.306 + * iterator will make a best effort to locate and instantiate the next 4.307 + * available provider, but in general such recovery cannot be guaranteed. 4.308 + * 4.309 + * <blockquote style="font-size: smaller; line-height: 1.2"><span 4.310 + * style="padding-right: 1em; font-weight: bold">Design Note</span> 4.311 + * Throwing an error in these cases may seem extreme. The rationale for 4.312 + * this behavior is that a malformed provider-configuration file, like a 4.313 + * malformed class file, indicates a serious problem with the way the Java 4.314 + * virtual machine is configured or is being used. As such it is 4.315 + * preferable to throw an error rather than try to recover or, even worse, 4.316 + * fail silently.</blockquote> 4.317 + * 4.318 + * <p> The iterator returned by this method does not support removal. 4.319 + * Invoking its {@link java.util.Iterator#remove() remove} method will 4.320 + * cause an {@link UnsupportedOperationException} to be thrown. 4.321 + * 4.322 + * @return An iterator that lazily loads providers for this loader's 4.323 + * service 4.324 + */ 4.325 + public Iterator<S> iterator() { 4.326 + return new Iterator<S>() { 4.327 + 4.328 + Iterator<Map.Entry<String,S>> knownProviders 4.329 + = providers.entrySet().iterator(); 4.330 + 4.331 + public boolean hasNext() { 4.332 + if (knownProviders.hasNext()) 4.333 + return true; 4.334 + return lookupIterator.hasNext(); 4.335 + } 4.336 + 4.337 + public S next() { 4.338 + if (knownProviders.hasNext()) 4.339 + return knownProviders.next().getValue(); 4.340 + return lookupIterator.next(); 4.341 + } 4.342 + 4.343 + public void remove() { 4.344 + throw new UnsupportedOperationException(); 4.345 + } 4.346 + 4.347 + }; 4.348 + } 4.349 + 4.350 + /** 4.351 + * Creates a new service loader for the given service type and class 4.352 + * loader. 4.353 + * 4.354 + * @param service 4.355 + * The interface or abstract class representing the service 4.356 + * 4.357 + * @param loader 4.358 + * The class loader to be used to load provider-configuration files 4.359 + * and provider classes, or <tt>null</tt> if the system class 4.360 + * loader (or, failing that, the bootstrap class loader) is to be 4.361 + * used 4.362 + * 4.363 + * @return A new service loader 4.364 + */ 4.365 + public static <S> ServiceLoader<S> load(Class<S> service, 4.366 + ClassLoader loader) 4.367 + { 4.368 + return new ServiceLoader<>(service, loader); 4.369 + } 4.370 + 4.371 + /** 4.372 + * Creates a new service loader for the given service type, using the 4.373 + * current thread's {@linkplain java.lang.Thread#getContextClassLoader 4.374 + * context class loader}. 4.375 + * 4.376 + * <p> An invocation of this convenience method of the form 4.377 + * 4.378 + * <blockquote><pre> 4.379 + * ServiceLoader.load(<i>service</i>)</pre></blockquote> 4.380 + * 4.381 + * is equivalent to 4.382 + * 4.383 + * <blockquote><pre> 4.384 + * ServiceLoader.load(<i>service</i>, 4.385 + * Thread.currentThread().getContextClassLoader())</pre></blockquote> 4.386 + * 4.387 + * @param service 4.388 + * The interface or abstract class representing the service 4.389 + * 4.390 + * @return A new service loader 4.391 + */ 4.392 + public static <S> ServiceLoader<S> load(Class<S> service) { 4.393 + ClassLoader cl = Thread.currentThread().getContextClassLoader(); 4.394 + return ServiceLoader.load(service, cl); 4.395 + } 4.396 + 4.397 + /** 4.398 + * Creates a new service loader for the given service type, using the 4.399 + * extension class loader. 4.400 + * 4.401 + * <p> This convenience method simply locates the extension class loader, 4.402 + * call it <tt><i>extClassLoader</i></tt>, and then returns 4.403 + * 4.404 + * <blockquote><pre> 4.405 + * ServiceLoader.load(<i>service</i>, <i>extClassLoader</i>)</pre></blockquote> 4.406 + * 4.407 + * <p> If the extension class loader cannot be found then the system class 4.408 + * loader is used; if there is no system class loader then the bootstrap 4.409 + * class loader is used. 4.410 + * 4.411 + * <p> This method is intended for use when only installed providers are 4.412 + * desired. The resulting service will only find and load providers that 4.413 + * have been installed into the current Java virtual machine; providers on 4.414 + * the application's class path will be ignored. 4.415 + * 4.416 + * @param service 4.417 + * The interface or abstract class representing the service 4.418 + * 4.419 + * @return A new service loader 4.420 + */ 4.421 + public static <S> ServiceLoader<S> loadInstalled(Class<S> service) { 4.422 + ClassLoader cl = ClassLoader.getSystemClassLoader(); 4.423 + ClassLoader prev = null; 4.424 + while (cl != null) { 4.425 + prev = cl; 4.426 + cl = cl.getParent(); 4.427 + } 4.428 + return ServiceLoader.load(service, prev); 4.429 + } 4.430 + 4.431 + /** 4.432 + * Returns a string describing this service. 4.433 + * 4.434 + * @return A descriptive string 4.435 + */ 4.436 + public String toString() { 4.437 + return "java.util.ServiceLoader[" + service.getName() + "]"; 4.438 + } 4.439 + 4.440 +}
5.1 --- a/test/tools/javac/plugin/showtype/Test.java Tue May 07 06:39:34 2013 -0700 5.2 +++ b/test/tools/javac/plugin/showtype/Test.java Tue May 07 14:27:30 2013 -0700 5.3 @@ -1,5 +1,5 @@ 5.4 /* 5.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 5.6 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 5.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.8 * 5.9 * This code is free software; you can redistribute it and/or modify it 5.10 @@ -23,7 +23,7 @@ 5.11 5.12 /** 5.13 * @test 5.14 - * @bug 8001098 8004961 5.15 + * @bug 8001098 8004961 8004082 5.16 * @summary Provide a simple light-weight "plug-in" mechanism for javac 5.17 */ 5.18