Save This Page
Home » openjdk-7 » sun » misc » [javadoc | source]
    1   /*
    2    * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package sun.misc;
   27   
   28   /**
   29    * Provides utility functions related to URLClassLoaders or subclasses of it.
   30    *
   31    *                  W  A  R  N  I  N  G
   32    *
   33    * This class uses undocumented, unpublished, private data structures inside
   34    * java.net.URLClassLoader and sun.misc.URLClassPath.  Use with extreme caution.
   35    *
   36    * @author      tjquinn
   37    */
   38   
   39   
   40   import java.io.IOException;
   41   import java.net.URLClassLoader;
   42   import java.util;
   43   import java.util.jar.JarFile;
   44   
   45   public class ClassLoaderUtil {
   46   
   47       /**
   48        * Releases resources held by a URLClassLoader. A new classloader must
   49        * be created before the underlying resources can be accessed again.
   50        * @param classLoader the instance of URLClassLoader (or a subclass)
   51        */
   52       public static void releaseLoader(URLClassLoader classLoader) {
   53           releaseLoader(classLoader, null);
   54       }
   55   
   56       /**
   57        * Releases resources held by a URLClassLoader.  Notably, close the jars
   58        * opened by the loader. Initializes and updates the List of
   59        * jars that have been successfully closed.
   60        * <p>
   61        * @param classLoader the instance of URLClassLoader (or a subclass)
   62        * @param jarsClosed a List of Strings that will contain the names of jars
   63        *  successfully closed; can be null if the caller does not need the information returned
   64        * @return a List of IOExceptions reporting jars that failed to close; null
   65        * indicates that an error other than an IOException occurred attempting to
   66        * release the loader; empty indicates a successful release; non-empty
   67        * indicates at least one error attempting to close an open jar.
   68        */
   69       public static List<IOException> releaseLoader(URLClassLoader classLoader, List<String> jarsClosed) {
   70   
   71           List<IOException> ioExceptions = new LinkedList<IOException>();
   72   
   73           try {
   74               /* Records all IOExceptions thrown while closing jar files. */
   75   
   76               if (jarsClosed != null) {
   77                   jarsClosed.clear();
   78               }
   79   
   80               URLClassPath ucp = SharedSecrets.getJavaNetAccess()
   81                                                   .getURLClassPath(classLoader);
   82               ArrayList loaders = ucp.loaders;
   83               Stack urls = ucp.urls;
   84               HashMap lmap = ucp.lmap;
   85   
   86               /*
   87                *The urls variable in the URLClassPath object holds URLs that have not yet
   88                *been used to resolve a resource or load a class and, therefore, do
   89                *not yet have a loader associated with them.  Clear the stack so any
   90                *future requests that might incorrectly reach the loader cannot be
   91                *resolved and cannot open a jar file after we think we've closed
   92                *them all.
   93                */
   94               synchronized(urls) {
   95                   urls.clear();
   96               }
   97   
   98               /*
   99                *Also clear the map of URLs to loaders so the class loader cannot use
  100                *previously-opened jar files - they are about to be closed.
  101                */
  102               synchronized(lmap) {
  103                   lmap.clear();
  104               }
  105   
  106               /*
  107                *The URLClassPath object's path variable records the list of all URLs that are on
  108                *the URLClassPath's class path.  Leave that unchanged.  This might
  109                *help someone trying to debug why a released class loader is still used.
  110                *Because the stack and lmap are now clear, code that incorrectly uses a
  111                *the released class loader will trigger an exception if the
  112                *class or resource would have been resolved by the class
  113                *loader (and no other) if it had not been released.
  114                *
  115                *The list of URLs might provide some hints to the person as to where
  116                *in the code the class loader was set up, which might in turn suggest
  117                *where in the code the class loader needs to stop being used.
  118                *The URLClassPath does not use the path variable to open new jar
  119                *files - it uses the urls Stack for that - so leaving the path variable
  120                *will not by itself allow the class loader to continue handling requests.
  121                */
  122   
  123               /*
  124                *For each loader, close the jar file associated with that loader.
  125                *
  126                *The URLClassPath's use of loaders is sync-ed on the entire URLClassPath
  127                *object.
  128                */
  129               synchronized (ucp) {
  130                   for (Object o : loaders) {
  131                       if (o != null) {
  132                           /*
  133                            *If the loader is a JarLoader inner class and its jarFile
  134                            *field is non-null then try to close that jar file.  Add
  135                            *it to the list of closed files if successful.
  136                            */
  137                           if (o instanceof URLClassPath.JarLoader) {
  138                                   URLClassPath.JarLoader jl = (URLClassPath.JarLoader)o;
  139                                   JarFile jarFile = jl.getJarFile();
  140                                   try {
  141                                       if (jarFile != null) {
  142                                           jarFile.close();
  143                                           if (jarsClosed != null) {
  144                                               jarsClosed.add(jarFile.getName());
  145                                           }
  146                                       }
  147                                   } catch (IOException ioe) {
  148                                       /*
  149                                        *Wrap the IOException to identify which jar
  150                                        *could not be closed and add it to the list
  151                                        *of IOExceptions to be returned to the caller.
  152                                        */
  153                                       String jarFileName = (jarFile == null) ? "filename not available":jarFile.getName();
  154                                       String msg = "Error closing JAR file: " + jarFileName;
  155                                       IOException newIOE = new IOException(msg);
  156                                       newIOE.initCause(ioe);
  157                                       ioExceptions.add(newIOE);
  158                                   }
  159                           }
  160                       }
  161                   }
  162                   /*
  163                    *Now clear the loaders ArrayList.
  164                    */
  165                   loaders.clear();
  166               }
  167           } catch (Throwable t) {
  168               throw new RuntimeException (t);
  169           }
  170           return ioExceptions;
  171       }
  172   }

Save This Page
Home » openjdk-7 » sun » misc » [javadoc | source]