JVM学习笔记003:类加载与字节码技术
发布日期:2021-04-30 21:03:49 浏览次数:82 分类:精选文章

本文共 2221 字,大约阅读时间需要 7 分钟。

JVM学习笔记:类加载与字节码技术

在学习Java虚拟机(JVM)时,类加载与字节码技术是非常关键的一部分。本文将从类文件结构、字节码指令、编译期处理、类加载阶段以及运行期优化等方面,系统地整理相关知识。


1. 类文件结构

1.1 魔数

类文件的开头4个字节是魔数(Magic Number),用于标识这是一个Java类文件,而不是其他类型的文件。例如,ca fe ba be对应的十进制值为0xCAFEBABE,表示JDK 8及以上版本。

1.2 版本

接下来的2个字节分别表示minor version(次小版本)和major version(大版本)。例如,00 00 34表示major version为52,对应JDK 8。

1.3 常量池

常量池是类文件中存储常量的区域,包含字符串、数字、字段、方法等的引用信息。常量池的大小由前面的2个字节决定,例如00 23表示常量池有35个项。

1.4 访问标志

接下来的2个字节是访问标志(Access Flags),表示类的访问权限和其他属性,例如public、final、super等。

1.5 类和超类

表示该类的Class对象和其直接继承的超类Class对象。

1.6 接口计数

接下来的2个字节是接口计数,表示该类实现了多少个接口。

1.7 字段计数

接下来的2个字节是字段计数,表示类中有多少个字段。

1.8 方法计数

接下来的2个字节是方法计数,表示类中有多少个方法。

1.9 属性计数

接下来的2个字节是属性计数,表示类中有多少个属性(注解相关)。


2. 字节码指令

2.1 语法糖

Java编译器会在编译阶段生成一些额外的代码,称为语法糖。例如:

  • 匿名内部类:编译器会生成额外的类来表示匿名内部类。
  • 可变参数String... args会被转换为String[] args
  • foreach循环for (int x : array)会被转换为传统的循环结构。

2.2 字节码指令

Java字节码指令是虚拟机执行程序的基本单位。常见指令包括:

  • istore:将操作数栈中的元素存入局部变量表。
  • iload:将局部变量表中的元素加载到操作数栈。
  • iadd:将操作数栈中的两个元素相加。
  • getstatic:读取类字段。
  • invokevirtual:调用对象的方法。

2.3 反编译工具

Oracle提供了javap工具,可以用来反编译类文件。例如,可以使用javap -v HelloWorld.class来查看类文件的详细信息。


3. 编译期处理

3.1 构造方法

Java编译器会自动生成类的构造方法<init>,并包含父类Object的默认构造方法。

3.2 拆箱与装箱

Java自动处理基本类型与包装类型之间的转换。例如,Integer x = 1;会自动拆箱为intx = 1;

3.3 泛型擦除

在编译期,Java会擦除泛型信息,将泛型类型转换为普通Object类型。


4. 类加载阶段

4.1 加载

类加载器将类文件加载到方法区。JVM默认使用Bootstrap ClassLoader加载核心Java类。

4.2 双亲委派

当类加载器无法加载类时,会调用其上级类加载器(parent ClassLoader)加载。如果上级类加载器也无法加载,则默认调用Bootstrap ClassLoader。

4.3 解析

在类加载过程中,常量池中的符号引用会被解析为直接引用。例如,com.example.MyClass会被转换为com.example.MyClass的内存地址。

4.4 初始化

初始化阶段会执行clinit()方法,包括静态变量的初始化和静态代码块。


5. 运行期优化

5.1 即时编译器

JVM使用即时编译器(JIT)将字节码转换为机器码,以提升性能。C1和C2是两种不同的即时编译器。

5.2 逃逸分析

逃逸分析减少了内存分配,提高了性能。例如,未逃逸的对象可以在栈内存中分配,减少了GC压力。

5.3 锁消除

优化后的锁消除减少了锁的开销。例如,synchronized块中的方法可以被优化为无锁方法。

5.4 反射优化

反射调用会被优化为本地方法调用,以提高性能。


6. 方法调用

6.1 invokevirtual

用于调用对象的动态方法,支持多态。

6.2 invokespecial

用于调用构造函数或静态方法。

6.3 invokestatic

用于调用静态方法。


7. 异常处理

7.1 try-catch-finally

  • try:声明异常处理块。
  • catch:捕获特定异常类型。
  • finally:处理异常或定常执行的代码。

7.2 多个catch

异常表的结构允许多个catch块共享同一异常槽位。

7.3 吞掉异常

finally中使用return会吞掉异常。


8. Synchronized

monitorentermonitorexit用于管理同步。每个线程获得锁时,会在对象头中存储该线程的访问信息。


9. 枚举类

枚举类通过enum关键字定义。每个枚举常量都有一个ordinal值,用于确定其顺序。


10. 匿名内部类

匿名内部类不会有名字,可以引用外部类的成员变量或方法。编译器会生成一个额外的类来表示匿名内部类。


通过以上内容,可以系统地理解Java类文件的结构、字节码的执行过程以及JVM的内工作原理。

上一篇:制作后台(网页)所需要的步骤
下一篇:JSP 页面实现一个计算器功能

发表评论

最新留言

感谢大佬
[***.8.128.20]2026年06月12日 09时03分40秒