Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

0%

# 聊聊 Java 的类加载机制一

发表于 2020-11-08 分类于 Java ， 类加载 阅读次数： 阅读次数： Disqus：

一说到这个主题，想到的应该是双亲委派模型，不过讲的包括但不限于这个，主要内容是参考深入理解 Java 虚拟机书中的介绍，
一个类型的生命周期包含了七个阶段，加载，验证，准备，解析，初始化，使用，卸载。

- ## 加载

1. 通过一个类的全限定名来获取定义此类的二进制字节流
2. 将这个字节流代表的静态存储结构转化为方法区的运行时数据结构
3. 在内存中生成了一个代表这个类的 java.lang.Class 对象，作为方法区这个类的各种数据的访问入口

- ## 验证

1. 文件格式验证
2. 元数据验证
3. 字节码验证
4. 符号引用验证

- ## 准备

  准备阶段是正式为类中定义的变量（即静态变量，被static修饰的变量）分配内存并设置类变量初始值的阶段

- ## 解析

  解析阶段是 Java 虚拟机将常量池内的符号引用替换为直接引用的过程

以上验证、准备、解析 三个阶段又合称为链接阶段，链接阶段要做的是将加载到JVM中的二进制字节流的类数据信息合并到JVM的运行时状态中。

- ## 初始化

  类的初始化阶段是类加载过程的最后一个步骤，也是除了自定义类加载器之外将主动权交给了应用程序，其实就是执行类构造器()方法的过程，()并不是我们在 Java 代码中直接编写的方法，它是 Javac编译器的自动生成物，()方法是由编译器自动收集类中的所有类变量的复制动作和静态句块(static{}块)中的语句合并产生的，编译器收集的顺序是由语句在原文件中出现的顺序决定的，静态语句块中只能访问定义在静态语句块之前的变量，定义在它之后的变量，在前面的静态语句块可以复制，但是不能访问，同时还要保证父类的执行先于子类，然后保证多线程下的并发问题

最终，方法区会存储当前类类信息，包括类的静态变量、类初始化代码（定义静态变量时的赋值语句 和 静态初始化代码块）、实例变量定义、实例初始化代码（定义实例变量时的赋值语句实例代码块和构造方法）和实例方法，还有父类的类信息引用。