- 为了类的安全加载,jvm 底层默认实现为双亲委派,但是在实际开发中有没有 - 打破这种双亲委派机制的情况呢?
答案是肯定的:有
原理是什么?
前面从源码我们看到,在 ClassLoader 的 loadClass() 方法实现类具体的双亲委派逻辑,如果要打破就要用我们自己写的 ClassLoader,用我们自己的 loadClass() 方法了。这样就简单了。只需要重写 ClassLoader 的 loadClass() 方法即可!
源码,这块写的很轻清楚。
我们的目标就是让这里代码失效,换成自己的即可。
2.1 Jdk1.2 之前,自定义的 ClassLoader 均需要重写 loadClass() 方法
2.2 ThreadContextClassLoader 可以实现基础类调用实现类代码,通过 thread.setContextClassLoader 指定
2.3 热启动,热部署
在 idea 或者其他 tomcat 等工具中会用到,原理就是重写了 ClassLoader.loaderClass 方法。
下面给出例子:
2.3.1 正常的类加载
package com.yuhl.c2020.rebushu;
import com.yuhl.c2020.MyClassLoader;
/**
* @author yuhl
* @Date 2020/12/26 17:08
* @Classname NomalClassLoader
* @Description 正常部署
*/
public class NomalClassLoader {
public static void main(String[] args) throws Exception {
MyClassLoader msbClassLoader = new MyClassLoader();
Class clazz = msbClassLoader.loadClass("com.yuhl.c2020.LoadClassResource");
msbClassLoader = null;
System.out.println(clazz.hashCode()); //1163157884
msbClassLoader = null;
msbClassLoader = new MyClassLoader();
Class clazz1 = msbClassLoader.loadClass("com.yuhl.c2020.LoadClassResource");
System.out.println(clazz1.hashCode()); //1163157884
System.out.println(clazz == clazz1); //true
}
}
2.3.2 热部署的类加载
package com.yuhl.c2020.rebushu;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @author yuhl
* @Date 2020/12/26 17:08
* @Classname HotClassLoader
* @Description 热部署
*/
public class HotClassLoader {
private static class MyClassLoaderHot extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
File f = new File("D:/tmp/jvm/" + name.replace(".", "/").concat(".class"));
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 super.loadClass(name);
}
}
public static void main(String[] args) throws Exception {
MyClassLoaderHot m = new MyClassLoaderHot();
Class clazz = m.loadClass("com.yuhl.c2020.Miao");
m = new MyClassLoaderHot();
Class clazzNew = m.loadClass("com.yuhl.c2020.Miao");
System.out.println(clazz == clazzNew); //false
}
}
通过上面 2.3.1 和 2.3.2 比较很容易得出结论:真的可以热部署哦!
此处讨论的较为浅显,目的是明白有打破双亲委派机制的这种应用场景和原理存在。如需深入理解,请参见《深入java虚拟机》或看其他资料!
自律的艰辛总甜过懊悔的苦果!
专注于 java 后端技术及解决方案,善于总结,分享!
自律的艰辛总甜过懊悔的苦果!
专注于 java 后端技术及解决方案,善于总结,分享!
自律的艰辛总甜过懊悔的苦果!
专注于 java 后端技术及解决方案,善于总结,分享!