027-JVM-打破双亲委派机制

深藏阁楼爱情的钟 2023-09-28 20:07 223阅读 0赞

上一篇: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指定

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Zzandpbg_size_16_color_FFFFFF_t_70 1

2.3 热启动,热部署

在idea或者其他tomcat等工具中会用到,原理就是重写了ClassLoader.loaderClass方法。
下面给出例子:

2.3.1 正常的类加载

  1. package com.yuhl.c2020.rebushu;
  2. import com.yuhl.c2020.MyClassLoader;
  3. /**
  4. * @author yuhl
  5. * @Date 2020/12/26 17:08
  6. * @Classname NomalClassLoader
  7. * @Description 正常部署
  8. */
  9. public class NomalClassLoader {
  10. public static void main(String[] args) throws Exception {
  11. MyClassLoader msbClassLoader = new MyClassLoader();
  12. Class clazz = msbClassLoader.loadClass("com.yuhl.c2020.LoadClassResource");
  13. msbClassLoader = null;
  14. System.out.println(clazz.hashCode()); //1163157884
  15. msbClassLoader = null;
  16. msbClassLoader = new MyClassLoader();
  17. Class clazz1 = msbClassLoader.loadClass("com.yuhl.c2020.LoadClassResource");
  18. System.out.println(clazz1.hashCode()); //1163157884
  19. System.out.println(clazz == clazz1); //true
  20. }
  21. }

2.3.2热部署的类加载

  1. package com.yuhl.c2020.rebushu;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. /**
  7. * @author yuhl
  8. * @Date 2020/12/26 17:08
  9. * @Classname HotClassLoader
  10. * @Description 热部署
  11. */
  12. public class HotClassLoader {
  13. private static class MyClassLoaderHot extends ClassLoader {
  14. @Override
  15. public Class<?> loadClass(String name) throws ClassNotFoundException {
  16. File f = new File("D:/tmp/jvm/" + name.replace(".", "/").concat(".class"));
  17. if(!f.exists()) return super.loadClass(name);
  18. try {
  19. InputStream is = new FileInputStream(f);
  20. byte[] b = new byte[is.available()];
  21. is.read(b);
  22. return defineClass(name, b, 0, b.length);
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. }
  26. return super.loadClass(name);
  27. }
  28. }
  29. public static void main(String[] args) throws Exception {
  30. MyClassLoaderHot m = new MyClassLoaderHot();
  31. Class clazz = m.loadClass("com.yuhl.c2020.Miao");
  32. m = new MyClassLoaderHot();
  33. Class clazzNew = m.loadClass("com.yuhl.c2020.Miao");
  34. System.out.println(clazz == clazzNew); //false
  35. }
  36. }

通过上面2.3.1和2.3.2比较很容易得出结论:真的可以热部署哦!

3. 总结

此处讨论的较为浅显,目的是明白有打破双亲委派机制的这种应用场景和原理存在。如需深入理解,请参见《深入java虚拟机》或看其他资料!

下一篇:028-JVM-类加载子系统面试题实战https://yuhongliang.blog.csdn.net/article/details/111799834

发表评论

表情:
评论列表 (有 0 条评论,223人围观)

还没有评论,来说两句吧...

相关阅读

    相关 双亲委派机制

    ![这里写图片描述][70] 上图中展示的类加载器之间的这种层次关系,称为类加载器的双亲委派模型。双亲委派模型除了顶层的启动类加载器之外,其余的类加载器都应当有自己的父类加