类加载机制--ClassLoader

什么是ClassLoader

写好的java程序,先被编译成class文件,然后才能被执行;类加载机制(ClassLoader)提了供动态加载class文件到jvm内存的功能。

类加载过程

在这里插入图片描述

  • 加载,指虚拟机查找class文件,并创建class对象的过程

  • 校验,保证class文件的字节流信息符合JVM规范
    文件格式验证:验证字节流文件是否符合Class文件格式的规范,并且能被当前虚拟机正确的处理。

    元数据验证:是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言的规范要求

    字节码验证:主要是进行数据流和控制流的分析,保证被 校验类的方法在运行时不会危害虚拟机。

    符号引用验证:符号引用验证发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在解析阶段中发生。

  • 准备,分配内存并设置变量的初始化值;

  • 解析,将常量池内的符号引用替换成直接引用

  • 初始化,静态变量的赋值和静态代码量的执行

java默认的类加载器
  • 启动类加载器 BootStrap classLoader,Java类加载层次中最顶层的类加载器,加载JDK核心类库
  • 扩展类加载器 Extonsion ClassLoader,负责加载java扩展类库
  • 应用程序类加载器 App ClassLoader,负责加载classpath 目录下所有jar和class文件
加载原理-双亲委托模型

每个ClassLoader实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。
双亲委派模型避免了类的重复加载

双亲委派模型的验证
package org.example;


class MyClassLoader extends ClassLoader {
    private String name;

    public MyClassLoader(String name) {
        this.name = name;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] data = getClassData(name);
        return defineClass(name, data, 0, data.length);
    }

    private byte[] getClassData(String className) {
        // 省略获取类字节码的过程
        return null;
    }
}


package org.example;

/**
 * @author xwg
 * @date 2023/4/6 22:34
 */
public class ClassLoaderDemo {
    public static void main(String[] args) {

        ClassLoader classLoader = ClassLoaderDemo.class.getClassLoader();
        System.out.println("ClassLoaderDemo的类加载器:"+ classLoader);
        // 获取系统类加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println("系统类加载器:" + systemClassLoader);

        // 获取系统类加载器的父类加载器,即扩展类加载器
        ClassLoader extensionClassLoader = systemClassLoader.getParent();
        System.out.println("扩展类加载器:" + extensionClassLoader);

        // 获取扩展类加载器的父类加载器,即启动类加载器,因为Bootstrap ClassLoader不是一个普通的Java类,返回为null
        ClassLoader bootstrapClassLoader = extensionClassLoader.getParent();
        System.out.println("启动类加载器:" + bootstrapClassLoader);

        // 尝试使用自定义类加载器加载系统类库中的类
        try {
            MyClassLoader myClassLoader = new MyClassLoader("myClassLoader");
            Class<?> clazz = myClassLoader.loadClass("java.lang.String");
            System.out.println("自定义类加载器加载String类的结果:" + clazz.getClassLoader());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

ClassLoader 常用API

  • ClassLoader类是一个抽象类 ApplicationClassLoader和ExtensionClassLoader具体实现类是在sun.misc.launcher类中,BootStrapClassLoader不是java实现的;

  • 每个class对象都有一个方法可以获取加载他的ClassLoader

    public ClassLoader getClassLoader()
    
  • Classloader 常用方法

    //获取父ClassLoader
    public final ClassLoader getParent()
    
    //获取系统类加载器,静态方法
    public static ClassLoader getSystemClassLoader()
    
    //加载类
    public Class<?> loadClass(String name) throws 		ClassNotFoundException 
    
    //查找已加载的类
    protected final Class<?> findLoadedClass(String name)
    
    //defineClass 此方法负责将二进制字节流转换为Class对象
     protected final Class<?> defineClass(String name, byte[] b, int off, int len,ProtectionDomain protectionDomain)
        throws ClassFormatError
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值