027-JVM-打破双亲委派机制
上一篇:026-JVM-jvm对类的延时加载https://yuhongliang.blog.csdn.net/article/details/111600183
- 为了类的安全加载,jvm底层默认实现为双亲委派,但是在实际开发中有没有 - 打破这种双亲委派机制的情况呢?
答案是肯定的:有
1. 打破双亲委派的原理
原理是什么?
前面从源码我们看到,在ClassLoader的loadClass()方法实现类具体的双亲委派逻辑,如果要打破就要用我们自己写的ClassLoader,用我们自己的loadClass()方法了。这样就简单了。只需要重写ClassLoader的loadClass()方法即可!
源码,这块写的很轻清楚。
我们的目标就是让这里代码失效,换成自己的即可。
2. 目前打破双亲委派的三种情况
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比较很容易得出结论:真的可以热部署哦!
3. 总结
此处讨论的较为浅显,目的是明白有打破双亲委派机制
的这种应用场景和原理存在。如需深入理解,请参见《深入java虚拟机
》或看其他资料!
下一篇:028-JVM-类加载子系统面试题实战https://yuhongliang.blog.csdn.net/article/details/111799834
还没有评论,来说两句吧...