src/share/classes/com/sun/tools/javac/util/CloseableURLClassLoader.java

Mon, 10 Jan 2011 15:08:31 -0800

author
jjg
date
Mon, 10 Jan 2011 15:08:31 -0800
changeset 816
7c537f4298fb
parent 581
f2fdd52e4e87
permissions
-rw-r--r--

6396503: javac should not require assertions enabled
Reviewed-by: mcimadamore

jjg@372 1 /*
ohair@554 2 * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
jjg@372 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@372 4 *
jjg@372 5 * This code is free software; you can redistribute it and/or modify it
jjg@372 6 * under the terms of the GNU General Public License version 2 only, as
ohair@554 7 * published by the Free Software Foundation. Oracle designates this
jjg@372 8 * particular file as subject to the "Classpath" exception as provided
ohair@554 9 * by Oracle in the LICENSE file that accompanied this code.
jjg@372 10 *
jjg@372 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@372 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@372 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@372 14 * version 2 for more details (a copy is included in the LICENSE file that
jjg@372 15 * accompanied this code).
jjg@372 16 *
jjg@372 17 * You should have received a copy of the GNU General Public License version
jjg@372 18 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@372 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@372 20 *
ohair@554 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@554 22 * or visit www.oracle.com if you need additional information or have any
ohair@554 23 * questions.
jjg@372 24 */
jjg@372 25
jjg@450 26 package com.sun.tools.javac.util;
jjg@372 27
jjg@372 28 import java.io.Closeable;
jjg@372 29 import java.io.IOException;
jjg@372 30 import java.lang.reflect.Field;
jjg@372 31 import java.net.URL;
jjg@372 32 import java.net.URLClassLoader;
jjg@372 33 import java.util.ArrayList;
jjg@372 34 import java.util.jar.JarFile;
jjg@372 35
jjg@372 36 /**
jjg@372 37 * A URLClassLoader that also implements Closeable.
jjg@372 38 * Reflection is used to access internal data structures in the URLClassLoader,
jjg@372 39 * since no public API exists for this purpose. Therefore this code is somewhat
jjg@372 40 * fragile. Caveat emptor.
jjg@372 41 * @throws Error if the internal data structures are not as expected.
jjg@372 42 *
jjg@581 43 * <p><b>This is NOT part of any supported API.
jjg@581 44 * If you write code that depends on this, you do so at your own risk.
jjg@372 45 * This code and its internal interfaces are subject to change or
jjg@372 46 * deletion without notice.</b>
jjg@372 47 */
jjg@450 48 public class CloseableURLClassLoader
jjg@372 49 extends URLClassLoader implements Closeable {
jjg@450 50 public CloseableURLClassLoader(URL[] urls, ClassLoader parent) throws Error {
jjg@372 51 super(urls, parent);
jjg@372 52 try {
jjg@372 53 getLoaders(); //proactive check that URLClassLoader is as expected
jjg@372 54 } catch (Throwable t) {
jjg@372 55 throw new Error("cannot create CloseableURLClassLoader", t);
jjg@372 56 }
jjg@372 57 }
jjg@372 58
jjg@372 59 /**
jjg@372 60 * Close any jar files that may have been opened by the class loader.
jjg@372 61 * Reflection is used to access the jar files in the URLClassLoader's
jjg@372 62 * internal data structures.
jjg@372 63 * @throws java.io.IOException if the jar files cannot be found for any
jjg@372 64 * reson, or if closing the jar file itself causes an IOException.
jjg@372 65 */
jjg@450 66 @Override
jjg@372 67 public void close() throws IOException {
jjg@372 68 try {
jjg@372 69 for (Object l: getLoaders()) {
jjg@372 70 if (l.getClass().getName().equals("sun.misc.URLClassPath$JarLoader")) {
jjg@372 71 Field jarField = l.getClass().getDeclaredField("jar");
jjg@372 72 JarFile jar = (JarFile) getField(l, jarField);
jjg@407 73 if (jar != null) {
jjg@407 74 //System.err.println("CloseableURLClassLoader: closing " + jar);
jjg@407 75 jar.close();
jjg@407 76 }
jjg@372 77 }
jjg@372 78 }
jjg@372 79 } catch (Throwable t) {
jjg@372 80 IOException e = new IOException("cannot close class loader");
jjg@372 81 e.initCause(t);
jjg@372 82 throw e;
jjg@372 83 }
jjg@372 84 }
jjg@372 85
jjg@372 86 private ArrayList<?> getLoaders()
jjg@372 87 throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException
jjg@372 88 {
jjg@372 89 Field ucpField = URLClassLoader.class.getDeclaredField("ucp");
jjg@372 90 Object urlClassPath = getField(this, ucpField);
jjg@372 91 if (urlClassPath == null)
jjg@372 92 throw new AssertionError("urlClassPath not set in URLClassLoader");
jjg@372 93 Field loadersField = urlClassPath.getClass().getDeclaredField("loaders");
jjg@372 94 return (ArrayList<?>) getField(urlClassPath, loadersField);
jjg@372 95 }
jjg@372 96
jjg@372 97 private Object getField(Object o, Field f)
jjg@372 98 throws IllegalArgumentException, IllegalAccessException {
jjg@372 99 boolean prev = f.isAccessible();
jjg@372 100 try {
jjg@372 101 f.setAccessible(true);
jjg@372 102 return f.get(o);
jjg@372 103 } finally {
jjg@372 104 f.setAccessible(prev);
jjg@372 105 }
jjg@372 106 }
jjg@372 107
jjg@372 108 }

mercurial