乐趣区

关于jvm:JVM-解构类装载子系统

一: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 文件时,默认先交给父加载器去加载, 如果父加载器加载到就实现,当父加载器加载不到时候就会交给子加载器去加载,这就是双亲委派机制。

益处:

  1. 防止反复加载。
  2. 爱护程序平安,避免外围 api 被串改。

1.5 为什么须要自定加载类?

  1. 隔离加载类
  2. 批改类的加载形式
  3. 扩大加载源
  4. 避免源代码透露

阶段二:链接

链接阶段蕴含:验证 -> 筹备 -> 解析

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 

特点:

  1. 只有存在修饰符为 static 才会有 <clinit> 办法。
  2. 虚拟机须要保障 <clinit> 执行在多线程下须要加锁。
  3. 这个办法只执行一次。

留神:
<clinit> 跟 <init> 很像,然而 <init> 办法在 new 时候才会执行,这点须要留神。

下图可知有 static 润饰跟 <clinit> 办法关系:

**

**

欢送关注我公众号:

退出移动版