jvm之类加载机制


jvm将类的数据从class文件加载到内存中、形成可以被jvm直接使用的Class对象的过程成为类加载机制。

类的生命周期中的加载、验证、准备、解析、初始化属于类加载机制。
在这里插入图片描述

类加载的过程

1. 加载

通过类的全限定名获取二进制字节流、字节流转为方法区的运行时数据结构、在内存中生成代表这个类的java.lang.Class对象

2. 验证

确保Class文件的字节流包含的信息符合jvm的要求

3. 准备

为类中的静态变量分配内存并设置初始值

4. 解析

将常量池中的符号引用替换为直接引用

5. 初始化

真正执行编写的java程序代码,对类的静态变量进行初始化。与3中的初始化不同:3将静态变量初始化为默认值,例如整型则初始化为0;5将依据声明时指定的初始值、静态初始化块对静态变量进行初始化。

初始化的时机:
1. 创建类的实例时:通过new创建、通过反射创建、通过反序列化创建
2. 调用类的静态方法、访问或修改类的静态变量
3. 使用java.lang.reflect包的方法对类型进行反射调用时
4. 初始化某个类的子类,其所有父类都会被初始化
5. 直接使用java.exe运行某个主类,虚拟机会先初始化这个主类。
6. 当接口中包含default方法,如果这个接口的实现类进行了初始化,则这个接口要在其前被初始化

以上6种触发类初始化的方法成为主动引用。除此之外,所有引用类型的方式都不会触发初始化,称为被动引用:

  1. 通过子类引用父类的静态字段,不会导致子类初始化
  2. 通过数组定义引用类,不会触发此类的初始化
  3. 常量在编译阶段会进入类的常量池,本质上没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化

类加载器

类加载器负责将class文件加载到内存中,并为其生成对应的java.lang.Class对象。共有4类类加载器:

  1. Bootstrap ClassLoader:启动类加载器
  2. Extension ClassLoader:拓展类加载器
  3. Application ClassLoader:应用类加载器
  4. User ClassLoader: 自定义类加载器
    在这里插入图片描述

类加载机制:

  1. 全盘负责
    当一个类加载器负责加载某个Class时,该Class所依赖和引用的Class也由该类加载器负责,除非显式地使用另一个类加载器
  2. 双亲委托
    先让父加载器试图加载该Class,只有在父类加载器无法加载该Class时才尝试从自己的路径下加载
  3. 缓存机制
    所有加载过的类都会被缓存,当程序需要某个Class时,类加载器先从缓存中搜寻该Class,当不存在该Class时才进行加载。这也是修改Class后必须重新启动JVM,修改才生效的原因。

双亲委托的好处

  1. 沙箱安全机制:自己写的核心类和拓展类不会被加载,可以防止核心API被随意篡改

  2. 避免类的重复加载:当父亲已经加载了该类时,子类加载器不会重新加载一次

相关问题

1. new 一个对象背后发生了什么

2. 下面这段代码能运行吗?为什么

package java.lang;

public class String {
	public static void main(String[] args) {
		System.out.println("string");
	}
}

不能。报错如下:

java.lang.NoSuchMethodError: main
Exception in thread "main"

原因在于类加载机制中的双亲委托机制。根据双亲委托,在加载该类时会由Bootstrap ClassLoader进行加载且加载的是java核心库中的java.lang.String并非自定义的java.lang.String。核心库中的java.lang.String并没有Main方法所以会抛出NoSuchMethodError。

3. 能不能自定义一个类叫java.lang.System

看了第2题你可能会说不能,但是其实也能,通过自定义类加载器绕过双亲委托机制。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值