package com.stand.job.common.classload; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import com.stand.job.common.utils.ArrayUtils; /** * * @author chichaofan * * 若是delegateLoad 为false加载顺序以下 * * bootstrapsclassload -> extclassload -> 自定义各类类加载器 -> systemclassload * * 若是delegateLoad 为true为默认类加载器加载顺序以下 * * bootstrapsclassload -> extclassload ->systemclassload -> 自定义各类类加载器 */ public class StandJobClassLoader extends URLClassLoader { // 是否遵照双亲模式,默认双亲 private boolean delegateLoad = true; private ClassLoader javaseClassLoader; StandJobClassLoader(boolean delegateLoad) { super(new URL[] {}); this.delegateLoad = delegateLoad; setJavaseClassLoader(); } StandJobClassLoader(ClassLoader parent, boolean delegateLoad) { super(new URL[] {}, parent); this.delegateLoad = delegateLoad; setJavaseClassLoader(); } // 拷贝tomcat代码 private void setJavaseClassLoader() { ClassLoader j = String.class.getClassLoader(); if (j == null) { j = getSystemClassLoader(); while (j.getParent() != null) { j = j.getParent(); } } this.javaseClassLoader = j; } public void addJars(File[] files) { if (ArrayUtils.isEmpty(files)) { return; } for (File file : files) { addJar(file); } } public void addJar(File file) { if (file != null && file.isFile() && file.getName().toLowerCase().endsWith(".jar")) { try { addURL(file.toURI().toURL()); } catch (MalformedURLException e) { e.printStackTrace(); } } } protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { // 若是遵照双亲,调用原来 if (delegateLoad) { return super.loadClass(name, resolve); } Class<?> clazz = null; synchronized (getClassLoadingLock(name)) { /** * 判断是否已经加载 */ try { clazz = findLoadedClass(name); if (clazz != null) { if (resolve) { resolveClass(clazz); } return clazz; } } catch (Throwable e) { } /** * 先有bootstrapsclassload和 extclassload加载 */ try { clazz = javaseClassLoader.loadClass(name); if (clazz != null) { if (resolve) { resolveClass(clazz); } return clazz; } } catch (Throwable e) { } /** * 再是最外层自定义classlaod加载 */ try { clazz = super.findClass(name); if (clazz != null) { if (resolve) { resolveClass(clazz); } return clazz; } } catch (Throwable e) { } /** * 最外层加载不了,调用默认后续的加载器继续加载 */ try { clazz = super.loadClass(name, resolve); if (clazz != null) { if (resolve) { resolveClass(clazz); } return clazz; } } catch (Throwable e) { } /** * 加载不了跑出异常 */ throw new ClassNotFoundException(); } } }
测试例子:java
测试类bootstrap
package com.stand.job.example; public class JobServiceTest { public void run() { System.out.println("hello world" + getClass().getClassLoader().getClass()); } }
测试main,在当前测试项目中加入以上jar包,运行如下代码tomcat
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { File file = new File("/Users/chichaofan/Documents/doc/workspace/example/target/"); File[] files = file.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { if (name.toLowerCase().endsWith(".jar")) { return true; } return false; } }); for (File file2 : files) { StandJobClassLoader jobClassLoader = StandJobClassLoaderFactory.newInstance(false); jobClassLoader.addJar(file2); Object o = jobClassLoader.loadClass("com.stand.job.example.JobServiceTest").newInstance(); ReflectUtils.findMethod(o.getClass(), "run").invoke(o); } }
当delegateLoad为false时输出ide
hello worldclass com.stand.job.common.classload.StandJobClassLoader测试
当delegateLoad为true时输出this
hello worldclass sun.misc.Launcher$AppClassLoaderspa
由此看出当delegateLoad为false时加载器的加载顺序被改变了.net