diff --git a/changelog.html b/changelog.html index 720e40835d..5e4881d307 100644 --- a/changelog.html +++ b/changelog.html @@ -64,6 +64,9 @@ Upcoming changes
  • Allow BuildStep to work with non-AbstractProject (issue 23713) +
  • + Improved class loading performance when using Groovy. + (issue 24309)
  • Make the lifetime of queue items cache configurable. (issue 19691) diff --git a/core/src/main/java/hudson/PluginManager.java b/core/src/main/java/hudson/PluginManager.java index d47ac923c8..36f4880f77 100644 --- a/core/src/main/java/hudson/PluginManager.java +++ b/core/src/main/java/hudson/PluginManager.java @@ -435,6 +435,9 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas plugins.add(p); activePlugins.add(p); + synchronized (((UberClassLoader) uberClassLoader).loaded) { + ((UberClassLoader) uberClassLoader).loaded.clear(); + } try { p.resolvePluginDependencies(); @@ -1015,6 +1018,8 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas * Keyed by the generated class name. */ private ConcurrentMap> generatedClasses = new ConcurrentHashMap>(); + /** Cache of loaded, or known to be unloadable, classes. */ + private final Map> loaded = new HashMap>(); public UberClassLoader() { super(PluginManager.class.getClassLoader()); @@ -1033,13 +1038,35 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas else generatedClasses.remove(name,wc); } + if (name.startsWith("SimpleTemplateScript")) { // cf. groovy.text.SimpleTemplateEngine + throw new ClassNotFoundException("ignoring " + name); + } + synchronized (loaded) { + if (loaded.containsKey(name)) { + Class c = loaded.get(name); + if (c != null) { + return c; + } else { + throw new ClassNotFoundException("cached miss for " + name); + } + } + } if (FAST_LOOKUP) { for (PluginWrapper p : activePlugins) { try { Class c = ClassLoaderReflectionToolkit._findLoadedClass(p.classLoader, name); - if (c!=null) return c; + if (c != null) { + synchronized (loaded) { + loaded.put(name, c); + } + return c; + } // calling findClass twice appears to cause LinkageError: duplicate class def - return ClassLoaderReflectionToolkit._findClass(p.classLoader, name); + c = ClassLoaderReflectionToolkit._findClass(p.classLoader, name); + synchronized (loaded) { + loaded.put(name, c); + } + return c; } catch (ClassNotFoundException e) { //not found. try next } @@ -1053,6 +1080,9 @@ public abstract class PluginManager extends AbstractModelObject implements OnMas } } } + synchronized (loaded) { + loaded.put(name, null); + } // not found in any of the classloader. delegate. throw new ClassNotFoundException(name); }