fully implemented faster classloader lookup

This commit is contained in:
Kohsuke Kawaguchi committed 2011-10-10 18:54:55 +09:00
1 parent cd78f636cd
commit ee4e9c6149
3 files changed
+192 -57

No files matched your search

@@ -26,16 +26,25 @@ package hudson;
import hudson.Plugin.DummyImpl;
import hudson.PluginWrapper.Dependency;
import hudson.model.Hudson;
import hudson.util.CyclicGraphDetector;
import hudson.util.CyclicGraphDetector.CycleDetectedException;
import hudson.util.IOException2;
import hudson.util.IOUtils;
import hudson.util.MaskingClassLoader;
import hudson.util.VersionNumber;
import jenkins.ClassLoaderReflectionToolkit;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Expand;
import org.apache.tools.ant.types.FileSet;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
@@ -50,15 +59,8 @@ import java.util.jar.Manifest;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Expand;
import org.apache.tools.ant.types.FileSet;
public class ClassicPluginStrategy implements PluginStrategy {
private static final Logger LOGGER = Logger.getLogger(ClassicPluginStrategy.class.getName());
private final ClassLoaderReflectionToolkit clt = new ClassLoaderReflectionToolkit();
/**
* Filter for jar files.
@@ -167,7 +169,8 @@ public class ClassicPluginStrategy implements PluginStrategy {
for (DetachedPlugin detached : DETACHED_LIST)
detached.fix(atts,optionalDependencies);
ClassLoader dependencyLoader = new DependencyClassLoader(getBaseClassLoader(atts), archive, Util.join(dependencies,optionalDependencies));
ClassLoader dependencyLoader = new DependencyClassLoader(getClass().getClassLoader(), archive, Util.join(dependencies,optionalDependencies));
dependencyLoader = getBaseClassLoader(atts, dependencyLoader);
return new PluginWrapper(pluginManager, archive, manifest, baseResourceURL,
createClassLoader(paths, dependencyLoader, atts), disableFile, dependencies, optionalDependencies);
@@ -249,8 +252,7 @@ public class ClassicPluginStrategy implements PluginStrategy {
* <p>
* This mechanism allows plugins to have their own versions for libraries that core bundles.
*/
private ClassLoader getBaseClassLoader(Attributes atts) {
ClassLoader base = getClass().getClassLoader();
private ClassLoader getBaseClassLoader(Attributes atts, ClassLoader base) {
String masked = atts.getValue("Mask-Classes");
if(masked!=null)
base = new MaskingClassLoader(base, masked.trim().split("[ \t\r\n]+"));
@@ -413,22 +415,78 @@ public class ClassicPluginStrategy implements PluginStrategy {
private List<Dependency> dependencies;
/**
* Topologically sorted list of transient dependencies.
*/
private volatile List<PluginWrapper> transientDependencies;
public DependencyClassLoader(ClassLoader parent, File archive, List<Dependency> dependencies) {
super(parent);
this._for = archive;
this.dependencies = dependencies;
}
private List<PluginWrapper> getTransitiveDependencies() {
if (transientDependencies==null) {
CyclicGraphDetector<PluginWrapper> cgd = new CyclicGraphDetector<PluginWrapper>() {
@Override
protected List<PluginWrapper> getEdges(PluginWrapper pw) {
List<PluginWrapper> dep = new ArrayList<PluginWrapper>();
for (Dependency d : pw.getDependencies()) {
PluginWrapper p = pluginManager.getPlugin(d.shortName);
if (p!=null)
dep.add(p);
}
return dep;
}
};
try {
for (Dependency d : dependencies) {
PluginWrapper p = pluginManager.getPlugin(d.shortName);
if (p!=null)
cgd.run(Collections.singleton(p));
}
} catch (CycleDetectedException e) {
throw new AssertionError(e); // such error should have been reported earlier
}
transientDependencies = cgd.getSorted();
}
return transientDependencies;
}
// public List<PluginWrapper> getDependencyPluginWrappers() {
// List<PluginWrapper> r = new ArrayList<PluginWrapper>();
// for (Dependency d : dependencies) {
// PluginWrapper w = pluginManager.getPlugin(d.shortName);
// if (w!=null) r.add(w);
// }
// return r;
// }
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
for (Dependency dep : dependencies) {
PluginWrapper p = pluginManager.getPlugin(dep.shortName);
if(p!=null)
if (PluginManager.FAST_LOOKUP) {
for (PluginWrapper pw : getTransitiveDependencies()) {
try {
return p.classLoader.loadClass(name);
} catch (ClassNotFoundException _) {
// try next
Class c = clt.findLoadedClass(pw.classLoader,name);
if (c!=null) return c;
return clt.findClass(pw.classLoader,name);
} catch (InvocationTargetException e) {
//not found. try next
}
}
} else {
for (Dependency dep : dependencies) {
PluginWrapper p = pluginManager.getPlugin(dep.shortName);
if(p!=null)
try {
return p.classLoader.loadClass(name);
} catch (ClassNotFoundException _) {
// try next
}
}
}
throw new ClassNotFoundException(name);
@@ -437,12 +495,25 @@ public class ClassicPluginStrategy implements PluginStrategy {
@Override
protected Enumeration<URL> findResources(String name) throws IOException {
HashSet<URL> result = new HashSet<URL>();
for (Dependency dep : dependencies) {
PluginWrapper p = pluginManager.getPlugin(dep.shortName);
if (p!=null) {
Enumeration<URL> urls = p.classLoader.getResources(name);
while (urls != null && urls.hasMoreElements())
result.add(urls.nextElement());
if (PluginManager.FAST_LOOKUP) {
try {
for (PluginWrapper pw : getTransitiveDependencies()) {
Enumeration<URL> urls = clt.findResources(pw.classLoader, name);
while (urls != null && urls.hasMoreElements())
result.add(urls.nextElement());
}
} catch (InvocationTargetException e) {
throw new Error(e);
}
} else {
for (Dependency dep : dependencies) {
PluginWrapper p = pluginManager.getPlugin(dep.shortName);
if (p!=null) {
Enumeration<URL> urls = p.classLoader.getResources(name);
while (urls != null && urls.hasMoreElements())
result.add(urls.nextElement());
}
}
}
@@ -451,12 +522,23 @@ public class ClassicPluginStrategy implements PluginStrategy {
@Override
protected URL findResource(String name) {
for (Dependency dep : dependencies) {
PluginWrapper p = pluginManager.getPlugin(dep.shortName);
if(p!=null) {
URL url = p.classLoader.getResource(name);
if (url!=null)
return url;
if (PluginManager.FAST_LOOKUP) {
try {
for (PluginWrapper pw : getTransitiveDependencies()) {
URL url = clt.findResource(pw.classLoader,name);
if (url!=null) return url;
}
} catch (InvocationTargetException e) {
throw new Error(e);
}
} else {
for (Dependency dep : dependencies) {
PluginWrapper p = pluginManager.getPlugin(dep.shortName);
if(p!=null) {
URL url = p.classLoader.getResource(name);
if (url!=null)
return url;
}
}
}
@@ -483,4 +565,5 @@ public class ClassicPluginStrategy implements PluginStrategy {
}
public static boolean useAntClassLoader = Boolean.getBoolean(ClassicPluginStrategy.class.getName()+".useAntClassLoader");
private static final Logger LOGGER = Logger.getLogger(ClassicPluginStrategy.class.getName());
}