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();
}
}
}
测试例子:
测试类
package com.stand.job.example;
public class JobServiceTest {
public void run() {
System.out.println("hello world" + getClass().getClassLoader().getClass());
}
}
测试main,在当前测试项目中加入以上jar包,运行以下代码
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时输出
hello worldclass com.stand.job.common.classload.StandJobClassLoader
当delegateLoad为true时输出
hello worldclass sun.misc.Launcher$AppClassLoader
由此看出当delegateLoad为false时加载器的加载顺序被改变了