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

上一篇:026-JVM-jvm对类的延时加载https://yuhongliang.blog.csdn.net/article/details/111600183

  • 为了类的安全加载,jvm底层默认实现为双亲委派,但是在实际开发中有没有 - 打破这种双亲委派机制的情况呢?
    答案是肯定的:有

1. 打破双亲委派的原理

原理是什么?
前面从源码我们看到,在ClassLoader的loadClass()方法实现类具体的双亲委派逻辑,如果要打破就要用我们自己写的ClassLoader,用我们自己的loadClass()方法了。这样就简单了。只需要重写ClassLoader的loadClass()方法即可!
027-JVM-打破双亲委派机制_第1张图片
源码,这块写的很轻清楚。
我们的目标就是让这里代码失效,换成自己的即可。

2. 目前打破双亲委派的三种情况

2.1 Jdk1.2之前,自定义的ClassLoader均需要重写loadClass()方法

2.2 ThreadContextClassLoader可以实现基础类调用实现类代码,通过thread.setContextClassLoader指定

027-JVM-打破双亲委派机制_第2张图片

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

你可能感兴趣的:(java,jvm,java,开发语言,后端)