Changeset 1959
- Timestamp:
- 2011-12-22 14:42:36 (5 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/core/kauri-runtime/src/main/java/org/kauriproject/runtime/classloading/ClassLoaderBuilder.java
r967 r1959 16 16 package org.kauriproject.runtime.classloading; 17 17 18 import org.apache.commons.logging.Log; 19 import org.apache.commons.logging.LogFactory; 18 20 import org.kauriproject.runtime.repository.ArtifactRepository; 19 21 import org.kauriproject.runtime.repository.ArtifactNotFoundException; 20 22 23 import java.util.HashMap; 21 24 import java.util.List; 22 25 import java.util.ArrayList; … … 25 28 import java.net.MalformedURLException; 26 29 import java.io.File; 30 import java.util.Map; 27 31 28 32 public class ClassLoaderBuilder { 29 public static ClassLoader build(List<ClasspathEntry> classpathEntries, ClassLoader parentClassLoader, 33 private static Map<String, ClassLoader> classLoaderCache; 34 private static boolean classLoaderCacheEnabled = true; 35 static { 36 classLoaderCacheEnabled = System.getProperty("kauri.cacheclassloaders") != null; 37 if (classLoaderCacheEnabled) { 38 classLoaderCache = new HashMap<String, ClassLoader>(); 39 } 40 } 41 42 public static synchronized ClassLoader build(List<ClasspathEntry> classpathEntries, ClassLoader parentClassLoader, 43 ArtifactRepository repository) throws ArtifactNotFoundException, MalformedURLException { 44 45 if (classLoaderCacheEnabled) { 46 // 47 // About the ClassLoader cache: 48 // The ClassLoader cache was introduced to handle leaks in the 'Perm Gen' and 'Code Cache' 49 // JVM memory spaces when repeatedly restarting Kauri within the same JVM. In such cases, 50 // on each restart Kauri would construct new class loaders, hence the classes loaded through 51 // them would be new and would stress those JVM memory spaces. 52 // 53 // The solution here is good enough for what it is intended to do (restarting the same Kauri 54 // app, unchanged, many times). There is no cache cleaning and the cache key calculation 55 // is not perfect, so if you would enable the cache when starting a wide variety of Kauri 56 // apps within one VM or for reloading changed Kauri apps, it could be problematic. 57 // 58 StringBuilder cacheKeyBuilder = new StringBuilder(2000); 59 for (ClasspathEntry entry : classpathEntries) { 60 cacheKeyBuilder.append(entry.getArtifactRef()).append("\u2603" /* unicode snowman as separator */); 61 } 62 63 // Add some identification of the parent class loader 64 if (parentClassLoader instanceof URLClassLoader) { 65 for (URL url : ((URLClassLoader)parentClassLoader).getURLs()) { 66 cacheKeyBuilder.append(url.toString()); 67 } 68 } 69 70 String cacheKey = cacheKeyBuilder.toString(); 71 72 ClassLoader classLoader = classLoaderCache.get(cacheKey); 73 if (classLoader == null) { 74 Log log = LogFactory.getLog(ClassLoaderBuilder.class); 75 log.debug("Creating and caching a new classloader"); 76 classLoader = create(classpathEntries, parentClassLoader, repository); 77 classLoaderCache.put(cacheKey, classLoader); 78 } else if (classLoader.getParent() != parentClassLoader) { 79 Log log = LogFactory.getLog(ClassLoaderBuilder.class); 80 log.error("Kauri ClassLoader cache: parentClassLoader of cache ClassLoader is different" + 81 " from the specified one. Returning the cached one anyway."); 82 } 83 84 return classLoader; 85 } else { 86 return create(classpathEntries, parentClassLoader, repository); 87 } 88 } 89 90 private static ClassLoader create(List<ClasspathEntry> classpathEntries, ClassLoader parentClassLoader, 30 91 ArtifactRepository repository) throws ArtifactNotFoundException, MalformedURLException { 31 92 List<URL> classpath = new ArrayList<URL>(); … … 36 97 } 37 98 38 return new URLClassLoader(classpath.toArray(new URL[classpath.size()]), parentClassLoader); 99 return new URLClassLoader(classpath.toArray(new URL[classpath.size()]), parentClassLoader); 39 100 } 40 101 }
Note: See TracChangeset
for help on using the changeset viewer.