如果需要热部署,使用“双亲委派”是不行的,如何打破“双亲委派”呢~
一. 源代码
“双亲委派”源代码如下(ClassLoader.java):
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
二. 模拟热加载
public class Hello {
public Hello() {
}
public void test(){
System.out.println(System.currentTimeMillis() + " => hello world");
}
}
public class MyClassLoader extends ClassLoader{
public static void main(String[] args) throws Exception {
MyClassLoader m = new MyClassLoader();
Class clazz = m.loadClass("com.test.Hello");
clazz.getDeclaredMethod("test").invoke(clazz.getDeclaredConstructor().newInstance());
while (true){
TimeUnit.SECONDS.sleep(5);
m = new MyClassLoader();
clazz = m.loadClass("com.test.Hello");
clazz.getDeclaredMethod("test").invoke(clazz.getDeclaredConstructor().newInstance());
}
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
String path = "D:/project/java/test/javaTest/target/classes/" + name.replace('.', '/') + ".class";
File f = new File(path);
if(!f.exists()) {
return super.loadClass(name);
}
try {
InputStream is = new FileInputStream(f);
byte[] b = new byte[is.available()];
is.read(b);
return defineClass(name, b, 0, b.length);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
运行结果:
1613700414784 => hello world
1613700419786 => hello world
1613700424787 => hello world
修改 Hello.java, 然后编译
public class Hello {
public Hello() {
}
public void test(){
System.out.println(System.currentTimeMillis() + " => hello world123");
}
}
运行结果:
1613700414784 => hello world
1613700419786 => hello world
1613700424787 => hello world
1613700429788 => hello world
1613700434789 => hello world
1613700439789 => hello world
1613700444789 => hello world
1613700449790 => hello world123
1613700454790 => hello world123
来源:oschina
链接:https://my.oschina.net/icefoxhz/blog/4955560