JVM class 装载过程

本文深入探讨Java类加载过程,包括双亲委派模型、自定义类加载器、上下文类加载器的作用及其实现方式。同时,文章还介绍了类加载的三个阶段:加载、连接和初始化,并详细解释了每个阶段的具体操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先看整个大流程
class 装载过程

一、加载(这是 ClassLoader 要做的事情)
ClassLoader 执行流程**
双亲模型

双亲模型

  1. 这是默认的 class 加载流程
  2. 一般我们写的代码都会在 AppClassLoader 中加载,Custom ClassLoader 是自定义 ClassLoader,后面在非双亲模型下大多是用这种方式加载,例如下面的代码:
public class Boy {
	
	public void getGirl() {
		Girl girl = new Girl();
		girl.sayHello();
	}

}
public class Girl {
	
	public void sayHello() {
		ClassLoader classLoader = this.getClass().getClassLoader();
		System.out.println("hello I'm in " + classLoader.getClass().getSimpleName());
	}
		
}
public class Test {
	
	public static void main(String[] args) {
		Boy boy = new Boy();
		boy.getGirl();
	}

}
// 输出
hello I'm in AppClassLoader
  1. 如果 底部的 ClassLoader 找不到需要的 class,会一直往上询问相应的 ClassLoader 是否有需要的 class,如果去到 Bootstrap ClassLoader 都没有,就会从 Bootstrap ClassLoader 一直往下,在对应的 class “管辖” 目录内尝试加载 class,如果一直都没有,就会抛出异常
  2. 也可以手动设置使用哪个加载器加载 class
    在这里插入图片描述
    在这里插入图片描述
  3. 同理如果要在 Bootstrap ClassLoader 加载 Girl 类的话在启动参数里面添加 -Xbootclasspath/a:D:/testClassLoader,其中 “D:/testClassLoader” 如下图,但是如果要获取到 Bootstrap ClassLoader 是不可能的,值为 null,因为 Bootstrap ClassLoader 是用 C++ 编写的,逻辑上并不存在 Bootstrap ClassLoader 的实体类
    在这里插入图片描述
  4. 用自定义 ClassLoader 加载
public class MyClassLoader extends ClassLoader {
	
	@Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        try {
            String clazzName = name.substring(name.lastIndexOf(".") + 1) + ".class";
            InputStream is = getClass().getResourceAsStream(clazzName);
            if (is == null) {
                return super.loadClass(name);
            }
            byte[] b = new byte[is.available()];
            is.read(b);
            return defineClass(name, b, 0, b.length);
        } catch (IOException e) {
            throw new ClassNotFoundException(name);
        }
    }
}

在这里插入图片描述

  1. 关于 ContextClassLoader (上下文 ClassLoader):作用是可以在不同 ClassLoader 之间传递 ClassLoader,可以通过 Thread.currentThread().getContextClassLoader(); 来获取,通过 Thread.currentThread().setContextClassLoader(cl); 来设置一个 ClassLoader 进去,至于用途嘛,看实际的需要了

  2. 关于 class 的读取,可以通过文件、字符串、网络流等任何形式,但是最终都是以二进制流的形式加载

非双亲模型
  1. Tomcat 的 WebAppClassLoader
  2. OSGI 的 ClassLoader
二、连接
  1. 验证:对文件格式、字节码、元数据、符号引用进行验证,尽可能保证 class 是正确可执行的
  2. 准备:内存分配、元数据区内对象属性初始赋值,例如 public static value = 1;这时 value 会赋值为 0;对于 final 会赋值为 1;
  3. 解析:符号引用解析为直接引用,例如:字符串的引用
三、初始化
  1. static 赋值 和 static{} 语句执行
  2. 子类和父类的先后初始化

最后,还有很多细节未能一一道明,还要不断努力,加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值