深入理解JVM张龙-P15-P20

在这里插入图片描述
在这里插入图片描述
数组类的Class对象不是由classloader创建的,是由Java虚拟机在动态运行期间创建的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
来自定义类加载器
在这里插入图片描述
loadclass方法会调用我们重写的findclass方法。findclass方法一定要重写
在这里插入图片描述

package com.kmoonwang.mywenda;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Random;
import java.util.UUID;

public class JVMlearning extends ClassLoader{
    private String classLoaderName;
    private final String fileExtension = ".class";
    private String path;//指定从什么地方去加载

    public void setPath(String path) {
        this.path = path;
    }

    public JVMlearning(String classLoaderName){
        super();  //将系统类加载器当作该类加载器的父加载器
        this.classLoaderName = classLoaderName;
    }

    public JVMlearning(ClassLoader parent,String classLoaderName){
        super(parent);//显示指定该类加载器的父加载器
        this.classLoaderName = classLoaderName;
    }

    @Override
    public String toString(){
        return "[" + classLoaderName + "]";
    }

    @Override
    protected Class<?> findClass(String className) throws ClassNotFoundException{
        System.out.println("findclass: "+className);
        System.out.println("class loader name: "+ this.classLoaderName);
        byte[] data = this.loadClassData(className);

        return this.defineClass(className,data,0,data.length);
    }

    private byte[] loadClassData(String name){
        InputStream is = null;
        byte[] data = null;
        ByteArrayOutputStream baos = null;

        try{
            name = name.replace(".","\\");
            is = new FileInputStream(new File(this.path+name + fileExtension));
            baos = new ByteArrayOutputStream();
            int ch = 0;

            while(-1 != (ch = is.read())){
                baos.write(ch);
            }
            data = baos.toByteArray();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                is.close();
                baos.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return data;
    }

    public static void main(String[] args) throws Exception{
        JVMlearning loader1 = new JVMlearning("loader1");
        loader1.setPath("C:\\Users\\Administrator\\Desktop\\");
        Class<?> clazz = loader1.loadClass("com.kmoonwang.mywenda.Solution");
        System.out.println("class1 hashcode: " + clazz.hashCode());
        Object obj = clazz.newInstance();

        System.out.println(obj);
        System.out.println(obj.getClass().getClassLoader());

        JVMlearning loader2 = new JVMlearning(loader1,"loader2");//loader2的父加载器是loader1
        loader2.setPath("C:\\Users\\Administrator\\Desktop\\");
        Class<?> clazz2 = loader2.loadClass("com.kmoonwang.mywenda.Solution");
        System.out.println("class2 hashcode: " + clazz2.hashCode());
        Object obj2 = clazz2.newInstance();
        System.out.println(obj2);
        System.out.println(obj.getClass().getClassLoader());

    }
}

defineclass方法
在这里插入图片描述
但是loadclass方法的查找类的顺序是先查找已被加载过的类,然后去看父加载器是否能够加载,最后使用findClass方法进行加载

在这里插入图片描述
当工程中的Solution.class没有删除的时候,这个时候自定义类加载器是不会使用的,因为它的父亲-系统类加载器可以进行加载。只有当Solution.class删除的时候,它的父亲无法完成加载,这个时候才会使用自定义加载器。
在同一个命名空间中,类只被加载一次。

下面都是使用的系统类加载器进行加载,类只被加载一次
在这里插入图片描述
下面是有两个类加载器加载,所以加载了两次。
在这里插入图片描述
下面都是使用loader1完成的加载,所以类只被加载了一次
在这里插入图片描述
在这里插入图片描述
类加载器之间的关系不是继承关系,是包含关系,同一个类实例化创建的两个类加载器loader1,loader2.loader1可以成为loader2的父加载器

类的卸载
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
打印卸载信息:-XX:+TraceClassUnloading
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
但是类没有被初始化并不意味着类不会被加载,因为
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
继续改造程序

下面把MyCat的class文件删除,留下MySample的class文件。因为是系统类加载器加载的MySample,当他尝试去加载MyCat的时候就找不到然后报错了

在这里插入图片描述
把MySample的class文件删除,如下所示,MySample使用loader1进行加载,当用loader1加载MyCat的时候,会先使用它的父加载器,即系统加载器,系统加载器加载成功就是用它来加载。
在这里插入图片描述
系统类加载器是看不到他的子类加载器loader1加载过的MySample.class的
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值