一: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>办法关系:
**
**
欢送关注我公众号: