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