JVM学习笔记中篇--再谈类的加载器


一、概述

在这里插入图片描述

1.类加载的分类

在这里插入图片描述

2.类加载器的必要性

在这里插入图片描述

3.命名空间

在这里插入图片描述

4.类加载机制的基本特征

在这里插入图片描述

二、复习:类的加载器分类

在这里插入图片描述

1.引导类加载器

在这里插入图片描述

2.扩展类加载器

在这里插入图片描述

3.系统类加载器

在这里插入图片描述

4.用户自定义类加载器

在这里插入图片描述

三、测试不同的类加载器

在这里插入图片描述

四、ClassLoader源码解析

在这里插入图片描述

1.ClassLoader的主要方法

在这里插入图片描述

  1. loadClass源码解析(满足双亲委派机制的主要逻辑就是在loadClass方法中实现的)

假设测试代码:ClassLoader.getSystemClassLoader.loadClass("com.atguigu.java.User")

涉及到对如下方法的使用
 protected Class<?> loadClass(String name, boolean resolve)//resolve:true-加载class的同时进行解析操作
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {//同步操作,保证只能加载一次
            // 首先,在缓存中判断是否已经加载同名的类
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                	//获取当前类加载器的父类加载器
                    if (parent != null) {
                    	//如果存在父类加载器,则调用父类加载器进行类的加载
                        c = parent.loadClass(name, false);
                    } else {//parent为null:父类加载器是引导类加载器
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {//当前类的加载器的父类加载器未加载此类 or 当前类的加载器未加载此类
                    //调用当前ClassLoad的findClass()
                    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;
        }
    }

2.SecureClassLoader与URLClassLoader

在这里插入图片描述

3.Class.forName()与ClassLoader.loadClass()

在这里插入图片描述

五、双亲委派机制

1.定义与本质

在这里插入图片描述

2.优势与劣势

在这里插入图片描述

3.破坏双亲委派机制

  1. 破坏双亲委派机制1
    在这里插入图片描述

  2. 破坏双亲委派机制2
    在这里插入图片描述

  3. 破坏双亲委派机制3
    在这里插入图片描述

4.热替换的实现

在这里插入图片描述
代码实现热替换案例:
1、先自定类加载器(下面有代码案例)
2、用死循环来模拟在一直运行的程序,每次循环都创建了一个新的类加载器

public class LoopRun {

    public static void main(String[] args) throws Exception {

       while (true){
           MyClassLoader myClassLoader = new MyClassLoader("D:\\代码包\\JVMDemo\\chapter08\\src\\com\\atguigu\\java\\");
           Class clazz = myClassLoader.findClass("Demo1.class");
           Object demo = clazz.newInstance();
           Method method = clazz.getMethod("hot");
           method.invoke(demo);
           Thread.sleep(5000);

       }

    }

}

六、沙箱安全机制

在这里插入图片描述

七、自定义类的加载器

在这里插入图片描述

1.实现方式

在这里插入图片描述

/**
 * 自定义ClassLoader
 *
 * @author xzt
 * @create 2021-01-19 15:28
 */
public class MyClassLoader extends ClassLoader {

    private String byteCodePath;//字节码文件的路径

    public MyClassLoader(String path) {
        this.byteCodePath = path;
    }

    public MyClassLoader(ClassLoader parent, String byteCodePath) {
        super(parent);
        this.byteCodePath = byteCodePath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        //获取字节码文件的完整路径
        String fileName = "";
        if (name.contains(".class")) {
            fileName = byteCodePath + name;
        } else {
            fileName = byteCodePath + name + ".class";
        }


        BufferedInputStream bis = null;
        ByteArrayOutputStream baos = null;
        int len = -1;
        try {
            //获取一个输入流
            bis = new BufferedInputStream(new FileInputStream(fileName));
            //获取一个字节数组输出流
            baos = new ByteArrayOutputStream();

            //具体读入数据并写出数据的过程
            byte[] data = new byte[1024];
            while ((len = bis.read(data)) != -1) {
                baos.write(data, 0, len);
            }

            //获取内存中完整的字节数据
            byte[] byteCode = baos.toByteArray();
            //调用defineClass将字节数组的数据转换为Class的实例
            Class clazz = defineClass(null, byteCode,0, byteCode.length);
            return clazz;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (baos != null){
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (bis != null){
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }

}

八、jdk9新特性

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值