类的加载和初始化 ---- new 一个对象时,在JVM 中的过程是什么

在程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过加载、连接、初始化三个步骤来对该类进行初始化。如果没有意外,JVM 将会连续完成这三个步骤,所以有时也把这三个步骤统称为类加载或类初始化。

类的加载

类加载指的是将类的 class 文件读入内存,并为之创建一个 java.lang.Class 对象,也就是说,当程序中使用任何类时,系统都会为之建立一个 java.lang.Class 对象。

类的加载由类加载器完成,类加载器通常由 JVM 提供,这些类加载器负责将 .class 文件(可能在磁盘上,也可能在网络上)加载到内存中,并为之生成一个 java.lang.Class 对象。

类的连接

当类被加载之后,系统为之生成一个对应的 Class 对象,接着将会进入连接阶段,连接阶段负责把类的二进制数据合并到 JRE 中。

类的连接又可分为如下三个阶段:

  1. 验证:这阶段用于检验被加载的类是否有正确的内部结构,并和其他类协调一致。
  2. 准备:类准备阶段负责为类变量分配内存,并设置默认初始值。
  3. 解析:将类的二进制数据中的符号引用替换成直接引用。

类的初始化

在类的初始化阶段,虚拟机负责对类进行初始化,主要就是对类变量进行初始化。对类变量指定初始值有两种方式:

  1. 声明类变量时指定初始值;
  2. 使用静态代码块为类变量指定初始值。

小总结

JVM 初始化一个类包含如下几个步骤:

  1. 假如这个类还没有被加载和连接,则程序先加载并连接该类。
  2. 假如该类的直接父类还没有被初始化,则先初始化其直接父类。
  3. 假如类中有初始化语句,则系统依次执行这些初始化语句。

当执行第 2 个步骤时,系统对直接父类的初始化步骤也是遵循 1~3 步骤;如果改直接父类又有直接父类,系统再次重复这三个步骤来初始化这个父类......以此类推,所以 JVM 最先初始化的总是 java.lang.Object 类。这个策略也称之为双亲委派策略

类初始化的时机

当 Java 程序首次通过下面 6 种方式来使用某个类或接口时,系统就会初始化该类和接口。

  • 创建类的实例。包括:使用 new 来创建实例;通过反射来创建实例,通过反序列化的方式来创建实例。
  • 调用某个类的类方法(静态方法)
  • 访问某个类或接口的类变量,或为该类变量赋值
  • 使用反射来强制创建某个类或接口对应的 java.lang.Class 对象
  • 初始化某个类的之类。初始化某个类的子类时,该子类的所有父类都会被初始化。
  • 直接使用 java.exe 命令来运行某个主类。当运行某个主类时,程序会先初始化该主类。

【特别注意】

对于一个 final 型的类变量,如果该类变量的值在编译时就能确定下来,这个类变量就是 “宏变量”,Java 编译器会直接这个类变量出现的地方直接替换成它的值(相当于使用了常量)。因此程序在使用该静态类变量时,并不会导致该类的初始化。

原文地址:https://www.cnblogs.com/luler/p/15242195.html