You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by da...@apache.org on 2008/03/15 22:31:17 UTC
svn commit: r637480 -
/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java
Author: dain
Date: Sat Mar 15 14:31:09 2008
New Revision: 637480
URL: http://svn.apache.org/viewvc?rev=637480&view=rev
Log:
Improved clean up on class loader destruction
Automatically set antiJarLockingFlag on Windows
Added debug logging messages about class loader cleanup
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java
Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java?rev=637480&r1=637479&r2=637480&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java Sat Mar 15 14:31:09 2008
@@ -33,23 +33,47 @@
import java.util.List;
import java.util.Map;
import java.util.Collections;
+import java.util.Set;
+import java.util.LinkedHashSet;
import java.util.jar.JarFile;
import org.apache.openejb.core.TempClassLoader;
import org.apache.openejb.core.AntiJarLockingClassLoader;
import org.apache.openejb.core.TempAntiJarLockingClassLoader;
import org.apache.openejb.util.URLs;
+import org.apache.openejb.util.Logger;
+import org.apache.openejb.util.LogCategory;
import org.apache.xbean.classloader.JarFileClassLoader;
+import org.apache.xbean.classloader.NamedClassLoader;
/**
* @version $Revision$ $Date$
*/
public class ClassLoaderUtil {
+ private static final Logger log = Logger.getInstance(LogCategory.OPENEJB, ClassLoaderUtil.class);
private static final Map<String,List<ClassLoader>> classLoadersByApp = new HashMap<String,List<ClassLoader>>();
- private static final Map<ClassLoader,List<String>> appsByClassLoader = new HashMap<ClassLoader,List<String>>();
+ private static final Map<ClassLoader, Set<String>> appsByClassLoader = new HashMap<ClassLoader,Set<String>>();
- private static boolean isAntiJarLocking() {
- return Boolean.getBoolean("antiJarLocking");
+ private static final boolean antiJarLocking;
+ static {
+ String value = null;
+ for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
+ if (entry.getKey() instanceof String && entry.getValue() instanceof String) {
+ if ("antiJarLocking".equalsIgnoreCase((String) entry.getKey())) {
+ value = (String) entry.getValue();
+ break;
+ }
+ }
+ }
+
+ if (value != null) {
+ antiJarLocking = Boolean.valueOf(value);
+ } else {
+ antiJarLocking = System.getProperty("os.name", "unknown").toLowerCase().startsWith("windows");
+ }
+ if (antiJarLocking) {
+ log.error("AntiJarLockingClassLoader enabled");
+ }
}
public static ClassLoader getContextClassLoader() {
@@ -62,7 +86,7 @@
public static URLClassLoader createClassLoader(String appId, URL[] urls, ClassLoader parent) {
URLClassLoader classLoader;
- if (isAntiJarLocking()) {
+ if (antiJarLocking) {
classLoader = new AntiJarLockingClassLoader(appId, urls, parent);
} else {
classLoader = new URLClassLoader(urls, parent);
@@ -75,9 +99,9 @@
}
classLoaders.add(classLoader);
- List<String> apps = appsByClassLoader.get(classLoader);
+ Set<String> apps = appsByClassLoader.get(classLoader);
if (apps == null) {
- apps = new ArrayList<String>(1);
+ apps = new LinkedHashSet<String>(1);
appsByClassLoader.put(classLoader, apps);
}
apps.add(appId);
@@ -86,8 +110,10 @@
}
public static void destroyClassLoader(ClassLoader classLoader) {
+ log.debug("Destroying classLoader " + toString(classLoader));
+
// remove from the indexes
- List<String> apps = appsByClassLoader.remove(classLoader);
+ Set<String> apps = appsByClassLoader.remove(classLoader);
if (apps != null) {
for (String app : apps) {
List<ClassLoader> classLoaders = classLoadersByApp.get(app);
@@ -111,12 +137,14 @@
}
public static void destroyClassLoader(String appId) {
+ log.debug("Destroying classLoaders for application " + appId);
+
List<ClassLoader> classLoaders = classLoadersByApp.remove(appId);
if (classLoaders != null) {
for (ClassLoader classLoader : classLoaders) {
// get the apps using the class loader
- List<String> apps = appsByClassLoader.get(classLoader);
- if (apps == null) apps = Collections.emptyList();
+ Set<String> apps = appsByClassLoader.get(classLoader);
+ if (apps == null) apps = Collections.emptySet();
// this app is no longer using the class loader
apps.remove(appId);
@@ -125,13 +153,18 @@
if (apps.isEmpty()) {
appsByClassLoader.remove(classLoader);
destroyClassLoader(classLoader);
+ } else {
+ log.debug("ClassLoader " + toString(classLoader) + " held open by the applications" + apps);
}
}
+ } else {
+ log.debug("No class loaders found for application " + appId + ": Known applications are " + classLoadersByApp.keySet());
}
+ ClassLoaderUtil.clearSunJarFileFactoryCache(appId);
}
public static URLClassLoader createTempClassLoader(ClassLoader parent) {
- if (isAntiJarLocking()) {
+ if (antiJarLocking) {
return new TempAntiJarLockingClassLoader(parent);
} else {
return new TempClassLoader(parent);
@@ -139,7 +172,7 @@
}
public static URLClassLoader createTempClassLoader(URL[] urls) {
- if (isAntiJarLocking()) {
+ if (antiJarLocking) {
return new TempAntiJarLockingClassLoader(urls);
} else {
return new TempClassLoader(urls);
@@ -147,7 +180,7 @@
}
public static URLClassLoader createTempClassLoader(URL[] urls, ClassLoader parent) {
- if (isAntiJarLocking()) {
+ if (antiJarLocking) {
return new TempAntiJarLockingClassLoader(urls, parent);
} else {
return new TempClassLoader(urls, parent);
@@ -168,6 +201,8 @@
}
public static void clearSunJarFileFactoryCache(String jarLocation) {
+ log.debug("Clearing Sun JarFileFactory cache for directory " + jarLocation);
+
try {
Class jarFileFactory = Class.forName("sun.net.www.protocol.jar.JarFileFactory");
@@ -184,7 +219,7 @@
for (Object item : fileCache.keySet()) {
URL url = (URL) item;
if (isParent(jarLocation, URLs.toFile(url))) {
- urls.add(url);
+ urls.add(url);
}
}
@@ -195,8 +230,12 @@
urlCache.remove(jarFile);
jarFile.close();
}
- } catch (Exception e) {
- e.printStackTrace();
+ } catch (ClassNotFoundException e) {
+ // not a sun vm
+ } catch (NoSuchFieldException e) {
+ // different version of sun vm?
+ } catch (Throwable e) {
+ log.error("Unable to clear Sun JarFileFactory cache", e);
}
}
@@ -242,6 +281,17 @@
deRegisterMethod.invoke(null, classLoader);
} catch (Throwable ignored) {
// there is nothing a user could do about this anyway
+ }
+ }
+
+ private static String toString(ClassLoader classLoader) {
+ if (classLoader == null) {
+ return "null";
+ } else if (classLoader instanceof NamedClassLoader) {
+ NamedClassLoader namedClassLoader = (NamedClassLoader) classLoader;
+ return namedClassLoader.getName() + "@" + System.identityHashCode(classLoader);
+ } else {
+ return classLoader.getClass().getSimpleName() + "@" + System.identityHashCode(classLoader);
}
}