【JVM】类加载机制:分析与验证
创始人
2024-02-11 17:21:52

一、加载

  • 将类的字节码载入方法区中,内部采用 C++ 的 instanceKlass 描述 java 类。它的重要 field 有:
    • _java_mirror : java 的类镜像,例如对 String 来说,就是 String.class,作用是把 klass 暴露给 java 使用
    • _super :父类
    • _fields :成员变量
    • _methods :方法
    • _constants :常量池
    • _class_loader :类加载器
    • _vtable :虚方法表
    • _itable :接口方法表
  • 如果这个类还有父类没有加载,先加载父类
  • 加载和链接可能是交替运行的

注意

  • instanceKlass 这样的【元数据】是存储在方法区(1.8 后的元空间内),但 _java_mirror 是存储在堆中
  • 可以通过前面介绍的 HSDB 工具查看

在这里插入图片描述

二、链接

1)验证

验证类是否符合 JVM规范,安全性检查

  • 修改 Verify.java 的魔数:将 cafebabe 修改为 cafebaby

    在这里插入图片描述

  • 解释执行结果:类格式错误

    PS F:\software\IDEA\JavaProjects\JvmTest\target\classes\org\example\classLoading\link> java Verify
    Error: A JNI error has occurred, please check your installation and try again
    Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 1128351301 in class file Verifyat java.lang.ClassLoader.defineClass1(Native Method)...
    

2)准备

为 static 变量分配空间,设置默认值

  • JDK 7 之前:static 变量 存储于 instanceKlass 末尾
  • JDK 7 开始:static 变量 存储于 _java_mirror(类.class对象) 末尾
  • 注意:final 类型的 static 变量
    • 基本类型常量、字符串常量:编译阶段值就确定了,赋值操作在本阶段完成
    • 引用类型常量:赋值操作在 初始化阶段 完成

3)解析

将自己在其他类的常量池中的符号引用解析为直接引用

类A没有解析为直接引用

public class Analysis{public static void main(String[] args) throws IOException {//1.访问类A的静态变量(基本类型、字符串)不会导致类A的初始化(解析)System.out.println(A.a);System.in.read();}
}
class A{final static int a=1;static int b=1;static {System.out.println("init");}
}
  1. 运行程序

  2. 执行命令行命令,查看当前进程id

    PS F:\software\IDEA\JavaProjects\JvmTest> jps
    13816 Analysis
    ...
    
  3. 进入 jdk 安装目录,执行命令打开 HSDB工具

    F:\software\Java\jdk1.8.0_333>java -cp ./lib/sa-jdi.jar sun.jvm.hotspot.HSDB
    
  4. 将 HSDB工具 链接到当前进程

    在这里插入图片描述

  5. 找到 Analysis 类的常量池,查看类A的引用

在这里插入图片描述

类A解析为直接引用

public class Analysis{public static void main(String[] args) throws IOException {//2.访问类变量导致初始化System.out.println(A.b);System.in.read();}
}
class A{final static int a=1;static int b=1;static {System.out.println("init");}
}
  1. 运行程序

  2. 执行命令行命令,查看当前进程id

    PS F:\software\IDEA\JavaProjects\JvmTest> jps
    4768 Analysis
    ...
    
  3. 进入 jdk 安装目录,执行命令打开 HSDB工具

    F:\software\Java\jdk1.8.0_333>java -cp ./lib/sa-jdi.jar sun.jvm.hotspot.HSDB
    
  4. 将 HSDB工具 链接到当前进程

    在这里插入图片描述

  5. 找到 Analysis 类的常量池,查看类A的引用

    在这里插入图片描述

三、初始化

1)()V 方法

初始化即调用 ()V ,虚拟机会保证 ()V 的线程安全

2)发生的时机

导致类初始化的情况:

  • main 方法所在的类
  • new
  • 首次访问类的 静态变量、静态方法
  • 子类初始化,如果父类还没初始化
  • Class.forName(String)

不会导致类初始化的情况 :

  • 类加载器的 loadClass 方法 :加载阶段
  • Class.forName(String,false) :加载阶段
  • 创建该类的数组不会触发初始化 :加载阶段
  • 访问 类.class :加载阶段
  • 访问类的 静态常量(基本类型和字符串) :链接-准备阶段

验证:导致类初始化的情况

public class Init {static {//1.main方法所在类。首先被初始化System.out.println("1.init:main方法所在类");}public static void main(String[] args) throws ClassNotFoundException {//2.newA newTest=new A();//3.子类初始化//4.访问类的 静态变量、静态方法int a=B.b;//5.Class.forName(String)Class.forName("org.example.classLoading.link.D");}
}
class A{static {System.out.println("2.init:new的类");}
}
class B extends C{static int b=1;static {System.out.println("4.init:访问类的静态变量、静态方法");}
}
class C{static {System.out.println("3.init:子类初始化");}
}
class D{static {System.out.println("5.init:Class.forName(String)");}
}
1.init:main方法所在类
2.init:new的类
3.init:子类初始化
4.init:访问类的静态变量、静态方法
5.init:Class.forName(String)

验证:不会导致类初始化的情况

public class Init {public static void main(String[] args) throws ClassNotFoundException {ClassLoader classLoader = Init.class.getClassLoader();//1.类加载器的 loadClass 方法 :加载阶段classLoader.loadClass("org.example.classLoading.link.A");//2.Class.forName(String,false) :加载阶段Class.forName("org.example.classLoading.link.A",false,classLoader);//3.创建该类的数组不会触发初始化 :加载阶段A[] arr=new A[2];//4.访问 类.class :加载阶段Class clazz = A.class;//5.访问类的 静态常量(基本类型和字符串) :链接-准备阶段int a=A.a;}
}
class A{static final int a=1;static {System.out.println("init A");}
}
Process finished with exit code 0

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...