1 23 24 package com.sun.appserv; 25 26 import java.io.IOException ; 27 import java.lang.reflect.Field ; 28 import java.net.URLClassLoader ; 29 import java.util.ArrayList ; 30 import java.util.HashMap ; 31 import java.util.Stack ; 32 import java.util.Vector ; 33 import java.util.jar.JarFile ; 34 import java.util.logging.Formatter ; 35 import java.util.logging.Level ; 36 import java.util.logging.Logger ; 37 import java.text.MessageFormat ; 38 import sun.misc.URLClassPath; 39 import com.sun.common.util.logging.LogDomains; 40 41 42 52 public class ClassLoaderUtil { 53 54 55 private static boolean isInitialized = false; 56 57 58 private static final String URLCLASSLOADER_UCP_FIELD_NAME = "ucp"; 59 60 private static final String URLCLASSPATH_LOADERS_FIELD_NAME = "loaders"; private static final String URLCLASSPATH_URLS_FIELD_NAME = "urls"; private static final String URLCLASSPATH_LMAP_FIELD_NAME = "lmap"; 64 private static final String URLCLASSPATH_JARLOADER_INNER_CLASS_NAME = "sun.misc.URLClassPath$JarLoader"; 65 private static final String URLCLASSPATH_JARLOADER_JARFILE_FIELD_NAME = "jar"; 66 67 68 private static Field jcpField; 69 private static Field loadersField; 70 private static Field urlsField; 71 private static Field lmapField; 72 private static Class jarLoaderInnerClass; 73 74 private static Field jarFileField; 75 76 private static boolean initDone = false; 77 78 85 private static void init() throws Throwable { 86 if ( ! initDone) { 87 initForClosingJars(); 88 initDone = true; 89 } 90 } 91 92 96 private static void initForClosingJars() throws NoSuchFieldException { 97 jcpField = getField(URLClassLoader .class, URLCLASSLOADER_UCP_FIELD_NAME); 98 loadersField = getField(URLClassPath.class, URLCLASSPATH_LOADERS_FIELD_NAME); 99 urlsField = getField(URLClassPath.class, URLCLASSPATH_URLS_FIELD_NAME); 100 lmapField = getField(URLClassPath.class, URLCLASSPATH_LMAP_FIELD_NAME); 101 102 jarLoaderInnerClass = getInnerClass(URLClassPath.class, URLCLASSPATH_JARLOADER_INNER_CLASS_NAME); 103 jarFileField = getField(jarLoaderInnerClass, URLCLASSPATH_JARLOADER_JARFILE_FIELD_NAME); 104 } 105 106 113 private static Field getField(Class cls, String fieldName) throws NoSuchFieldException { 114 try { 115 Field field = cls.getDeclaredField(fieldName); 116 field.setAccessible(true); 117 return field; 118 } catch (NoSuchFieldException nsfe) { 119 NoSuchFieldException e = new NoSuchFieldException (getMessage("classloaderutil.errorGettingField", fieldName)); 120 e.initCause(nsfe); 121 throw e; 122 } 123 124 } 125 126 131 private static Class getInnerClass(Class cls, String innerClassName) { 132 Class result = null; 133 Class [] innerClasses = cls.getDeclaredClasses(); 134 for (Class c : innerClasses) { 135 if (c.getName().equals(innerClassName)) { 136 result = c; 137 break; 138 } 139 } 140 return result; 141 } 142 143 150 public static void releaseLoader(URLClassLoader classLoader) { 151 releaseLoader(classLoader, null); 152 } 153 154 170 public static IOException [] releaseLoader(URLClassLoader classLoader, Vector <String > jarsClosed) { 171 172 IOException [] result = null; 173 174 try { 175 init(); 176 177 178 Vector <IOException > ioExceptions = new Vector <IOException >(); 179 180 if (jarsClosed != null) { 181 jarsClosed.clear(); 182 } 183 184 URLClassPath ucp = (URLClassPath) jcpField.get(classLoader); 185 ArrayList loaders = (ArrayList ) loadersField.get(ucp); 186 Stack urls = (Stack ) urlsField.get(ucp); 187 HashMap lmap = (HashMap ) lmapField.get(ucp); 188 189 197 synchronized(urls) { 198 urls.clear(); 199 } 200 201 205 synchronized(lmap) { 206 lmap.clear(); 207 } 208 209 225 226 232 synchronized (ucp) { 233 for (Object o : loaders) { 234 if (o != null) { 235 240 if (jarLoaderInnerClass.isInstance(o)) { 241 try { 242 JarFile jarFile = (JarFile ) jarFileField.get(o); 243 try { 244 if (jarFile != null) { 245 jarFile.close(); 246 if (jarsClosed != null) { 247 jarsClosed.add(jarFile.getName()); 248 } 249 } 250 } catch (IOException ioe) { 251 256 String jarFileName = (jarFile == null) ? getMessage("classloaderutil.jarFileNameNotAvailable") : jarFile.getName(); 257 String msg = getMessage("classloaderutil.errorClosingJar", jarFileName); 258 IOException newIOE = new IOException (msg); 259 newIOE.initCause(ioe); 260 ioExceptions.add(newIOE); 261 262 265 getLogger().log(Level.WARNING, msg, ioe); 266 } 267 } catch (Throwable thr) { 268 getLogger().log(Level.WARNING, "classloaderutil.errorReleasingJarNoName", thr); 269 } 270 } 271 } 272 } 273 276 loaders.clear(); 277 } 278 result = ioExceptions.toArray(new IOException [ioExceptions.size()]); 279 } catch (Throwable thr) { 280 getLogger().log(Level.WARNING, "classloaderutil.errorReleasingLoader", thr); 281 result = null; 282 } 283 284 return result; 285 } 286 287 291 private static Logger getLogger() { 292 return LogDomains.getLogger(LogDomains.CMN_LOGGER); 293 } 294 295 302 private static String getMessage(String key, Object ... o) { 303 String msg = getLogger().getResourceBundle().getString(key); 304 return MessageFormat.format(msg, o); 305 } 306 } 307 | Popular Tags |