JVM复习(三)-- 类加载器

1. 类加载过程

类加载分四个阶段:Loading、Linking、Initializing
在这里插入图片描述

在Loading阶段,类加载器将class加载到内存中,在Linking阶段对class文件的规范进行校验,通过校验后为静态变量赋默认值,并将静态变量的符号引用替换成直接引用,到初始化阶段再给静态变量赋予初始值。Class初始化后等待使用结束GC回收。

加深静态变量赋值理解的示例:

	public class test {
		static int i = 8;
		……
	}

类test在加载时,会先给i赋默认值0,再赋初值8。

2. class文件在内存中的内容组成

分两块:
(1) 加载到内存中的二进制文件
(2) 指向二进制文件的class对象
在这里插入图片描述

在类中调用另一个类时,会在Matespace(java8,元数据区)中生成一个指向内存中对应目标类的二进制文件的class文件,并通过该class解析该类在内存中的二进制字节码。

3. 类加载器的组成

类加载器由Bootstrap Classloader、Extension Classloader、Application Classloader、Custom Classloader四层组成,各层等级分明,分工明确。

(1) Bootstrap Classloader(根类加载器)

这一层负责加载JDK的核心JAR文件(jdk环境目录下lib/rt.jat,sun.boot.class.path路径下的内容)。Bootstrap Classloader通过C++实现,故在java代码中,类X调用X.getClassLoader()返回null时(java无法穿透C++代码),表示类X由Bootstrap Classloader加载。

例:

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

打印:
在这里插入图片描述
String类由Bootstrap Classloader加载。

(2) Extension Classloader(拓展类加载器)

这一层负责加载拓展包,即jdk环境目录下的jre/lib/ext/*.jar或由参数-Djava.ext.dirs指定的目录下的内容。

(3) Application Classloader(应用类加载器)

这一层负责加载classpath指定路径下的类。

(4) Custom Classloader(自定义类加载器)

4. 双亲委派机制

在这里插入图片描述

(1) 双亲委派机制

JVM对类的加载遵循按需加载原则,采用双亲委派机制轮询加载。

a. 当JVM加载一个类的时候,自底向上委派询问该类是否加载。当询问到类已经加载时,退出轮询。
b. 当询问到顶该类都未加载时,自顶向下委派进行类的查找和判定加载,成功加载到该类时退出轮询。
c. 当双亲委派轮询加载流程结束,该类都未加载时,将会抛出ClassNotFoundException异常

特征:从子到父,再从父到子。

(2) 双亲委派流程
在这里插入图片描述

(3) 双亲委派机制作用

双亲委派机制出于安全考虑:

a. 防止重复加载同一class文件。双亲委派机制通过自底向上委派询问所请求类是否已经加载,防止重复加载。
b. 确保核心class文件不被篡改。双亲委派机制分层清晰,各层分工明确,核心都由上层加载器加载,并且加载成功后,轮询机制保证其不会被重新加载。故不存在用户自定义核心模块替换原有模块引起的安全问题。

5. 父加载器

父加载器的定义并非加载器的加载器或继承父类。父子加载器的相互关系为上下层关系,相互独立。

  • 获取类加载器父类加载器示例:
public static void main(String[] args) {
    // 自定义类由AppClassLoader加载
    System.out.println(TestClass.class.getClassLoader());
    // AppClassLoader的父加载器为ExtClassLoader
	System.out.println(TestClass.class.getClassLoader().getParent());
	// ExtClassLoader的父加载器为BoostrapClassLoader,返回为null
	System.out.println(TestClass.class.getClassLoader().getParent().getParent());
	// BoostrapClassLoader为顶层,不存在父加载器,抛异常
	System.out.println(TestClass.class.getClassLoader().getParent().getParent().getParent());
}

打印:
在这里插入图片描述

6. 加载范围

查阅Launcher源码(sun.misc.Launcher)可见

  • sun.boot.class.path
    BoostrapClassLoader加载路径
  • java.ext.dirs
    ExtClassLoader加载路径
  • java.class.path
    AppClassLoader加载路径

* 双亲委派机制理解

双亲委派机制,可以想象成家里来客人的场景,各层类加载器从下到上分别为儿子、爸爸、爷爷、太爷爷,调用的类就是客人。
当家里有人敲门时,儿子前去开门,看是不是自己邀请了的客人,是就接待(返回结果)就完事了。结果发现不是自己的客人,于是向爸爸请示。爸爸发现不是自己的客人,于是向上请示爷爷。爷爷发现也不是自己的客人,于是请示太爷爷。太爷爷发现也不是自己的客人,于是翻阅好友列表(源码加载路径),如果是自己的好友就亲自邀请进门做客(加载),好生接待(返回)。结果找不到这号好友,所以交给爷爷处理。爷爷也找不到这号好友,于是交给爸爸处理。爸爸也找不到自己有这号好友,就交给儿子处理。最后,儿子查了查自己的好友列表,发现也没有这号朋友,结果报警了(ClassNotFoundException)。

后续阅读 JVM复习(四)-- 编译器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大迪吃小迪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值