共计 1465 个字符,预计需要花费 4 分钟才能阅读完成。
一:JVM 虚拟机
类装载子系统在虚构中的地位:
二:类装载子系统
类装载子系统三个阶段:加载 -> 链接 -> 初始化
阶段一:加载
通过全限定名获取类的二进制流,把文件的静态数据构造转换为办法区运行时数据结构,
并在内存中生成 java.lang.class
对象,提供拜访入口。
Java 零碎提供了三种加载器:疏导类加载器,扩大类加载器,利用类加载器;用户还能够自定义本人的加载器。
依照官网定义又能够分为:疏导类加载器, 自定义加载器(继承自 java.lang.ClassLoader
)
1.1 疏导类加载器
疏导类加载器由 c 或 c ++ 实现的,没有父加载器。
出于平安思考用来加载外围类库,只加载蕴含 java javax sum
结尾的类。
因为是 c 或 c ++ 实现的打印进去的类加载器名字是 null
如:java.lang.String
通过代码打印类加载正好是 null
1.2 扩大类加载器 ExtClassLoader
扩大类加载器由 java 语言编写,继承自 java.lang.ClassLoader
, 父亲为 疏导类加载器 。
从 java.ext.dirs
零碎属性或者 jdk 的 jre/lib/ext
子目录下加载。
咱们打印java.ext.dirs
能够看到加载的门路:
1.3 利用类加载器(零碎类加载器)AppClassLoader
利用类加载器又叫做零碎类加载器, 也是咱们编写 java 代码最罕用到的加载器,其父亲是 扩大类加载器
。
通过下图可知 ClassLoadTest
是由 AppClassLoad
加载器加载,
甚至晓得了 AppClassLoad
的父加载器是 ExtClassLoader
,ExtClassLoader
的父加载器是 null
也就是下面说的 疏导类加载器。
1.4 双亲委派机制
在加载某个 class 文件时,默认先交给父加载器去加载, 如果父加载器加载到就实现,当父加载器加载不到时候就会交给子加载器去加载,这就是双亲委派机制。
益处:
- 防止反复加载。
- 爱护程序平安,避免外围 api 被串改。
1.5 为什么须要自定加载类?
- 隔离加载类
- 批改类的加载形式
- 扩大加载源
- 避免源代码透露
阶段二:链接
链接阶段蕴含:验证 -> 筹备 -> 解析
2.1 验证
class 文件须要合乎虚拟机的要求,验证类的正确性,保障虚构平安。
如其一:class 文件须要 cafebabe
结尾的魔术词。
2.2 筹备
为动态变量(static 润饰的变量)分配内存,并且为它设置默认初始化值。
援用类型:null
浮点类型:0.0
整型:0
布尔型: false
。
如果动态变量被 final
润饰,那么该变量就是常量。
因为 final
润饰的变量会在编译的时候 javac xx.java
就会调配值,筹备阶段就会显式初始化。
如:final static int age = 18
筹备阶段间接将 age = 18
而非 age = 0
2.3 解析
将常量池的符号援用转换为间接援用。
阶段三:初始化
初始化阶段波及:类结构器。
3.1 类结构器 <clinit>()
该办法不须要本人去定义,是 javac 编译器 主动去收集类所有的动态变量和静态方法块的赋值动作,而后执行。
例如:static age = 18
链接中的筹备阶段会将 age = 0
<clinit> 中将 age = 18
特点:
- 只有存在修饰符为
static
才会有 <clinit> 办法。 - 虚拟机须要保障 <clinit> 执行在多线程下须要加锁。
- 这个办法只执行一次。
留神:
<clinit> 跟 <init> 很像,然而 <init> 办法在 new 时候才会执行,这点须要留神。
下图可知有 static 润饰跟 <clinit> 办法关系:
**
**
欢送关注我公众号: