学弟学妹们,如果你想吃透 Java字节码的话,看这篇就好了!(超级硬核,建议收藏2)

简介: 学弟学妹们,如果你想吃透 Java字节码的话,看这篇就好了!(超级硬核,建议收藏)

睁大眼睛瞧过去,感觉内容挺多的。同学们不要着急,我们来一行一行分析。


第 1 行:


Classfile /Users/maweiqing/Documents/GitHub/TechSisterLearnJava/codes/TechSister/target/classes/com/itwanger/jvm/Main.class


字节码文件的位置。


第 2 行:


Last modified 2021年4月15日; size 385 bytes


字节码文件的修改日期、文件大小。


第 3 行:


SHA-256 checksum 6688843e4f70ae8d83040dc7c8e2dd3694bf10ba7c518a6ea9b88b318a8967c


字节码文件的 SHA-256 值。


第 4 行:


Compiled from "Main.java"


说明该字节码文件编译自 Main.java 源文件。


第 5 行:


public class com.itwanger.jvm.Main


字节码文件的类全名。


第 6 行 minor version: 0,次版本号。


第 7 行 major version: 55,主版本号。


第 8 行:


flags: (0x0021) ACC_PUBLIC, ACC_SUPER


类访问标记,一共有 8 种。




表明当前类是 ACC_PUBLIC | ACC_SUPER。位运算符 | 的意思是如果相对应位是 0,则结果为 0,否则为 1,所以 0x0001 | 0x0020 的结果是 0x0021(需要转成二进制进行运算)。


第 9 行:


this_class: #3                          // com/itwanger/jvm/Main


当前类的索引,指向常量池中下标为 3 的常量,可以看得出当前类是 Main 类。


第 10 行:


super_class: #4                         // java/lang/Object


父类的索引,指向常量池中下标为 6 的常量,可以看得出当前类的父类是 Object 类。


第 11 行:


interfaces: 0, fields: 1, methods: 2, attributes: 1


当前类有 0 个接口,1 个字段(age),2 个方法(write()方法和缺省的默认构造方法),1 个属性(该类仅有的一个属性是 SourceFIle,包含了源码文件的信息)。


03、常量池


接下来是 Constant pool,也就是字节码文件最重要的常量池部分。可以把常量池理解为字节码文件中的资源仓库,主要存放两大类信息。


1)字面量(Literal),有点类似 Java 中的常量概念,比如文本字符串,final 常量等。


2)符号引用(Symbolic References),属于编译原理方面的概念,包括 3 种:


类和接口的全限定名(Fully Qualified Name)

字段的名称和描述符(Descriptor)

方法的名称和描述符

Java 虚拟机是在加载字节码文件的时候才进行的动态链接,也就是说,字段和方法的符号引用只有经过运行期转换后才能获得真正的内存地址。当 Java 虚拟机运行时,需要从常量池获取对应的符号引用,然后在类创建或者运行时解析并翻译到具体的内存地址上。


当前字节码文件中一共有 21 个常量,它们之间是有链接的,逐个分析会比较乱,我们采用顺藤摸瓜的方式,从上依次往下看,那些被链接的常量我们就点到为止。


注:


# 号后面跟的是索引,索引没有从 0 开始而是从 1 开始,是因为设计者考虑到,“如果要表达不引用任何一个常量的含义时,可以将索引值设为 0 来表示”(《深入理解 Java 虚拟机》描述的)。


= 号后面跟的是常量的类型,没有包含前缀 CONSTANT_ 和后缀 _info。


全文中提到的索引等同于下标,为了灵活描述,没有做统一。


第 1 个常量:


#1 = Methodref          #4.#18         // java/lang/Object."<init>":()V


类型为 Methodref,表明是用来定义方法的,指向常量池中下标为 4 和 18 的常量。


第 4 个常量:


#4 = Class              #21            // java/lang/Object


类型为 Class,表明是用来定义类(或者接口)的,指向常量池中下标为 21 的常量。


第 21 个常量:


#21 = Utf8               java/lang/Object


类型为 Utf8,UTF-8 编码的字符串,值为 java/lang/Object。


第 18 个常量:


#18 = NameAndType        #7:#8          // "<init>":()V


类型为 NameAndType,表明是字段或者方法的部分符号引用,指向常量池中下标为 7 和 8 的常量。


第 7 个常量:


#7 = Utf8               <init>


类型为 Utf8,UTF-8 编码的字符串,值为 <init>,表明为构造方法。


第 8 个常量:


#8 = Utf8               ()V


类型为 Utf8,UTF-8 编码的字符串,值为 ()V,表明方法的返回值为 void。


到此为止,第 1 个常量算是摸完了。组合起来的意思就是,Main 类使用的是默认的构造方法,来源于 Object 类。


第 2 个常量:


#2 = Fieldref           #3.#19         // com/itwanger/jvm/Main.age:I


类型为 Fieldref,表明是用来定义字段的,指向常量池中下标为 3 和 19 的常量。


第 3 个常量:


#3 = Class              #20            // com/itwanger/jvm/Main


类型为 Class,表明是用来定义类(或者接口)的,指向常量池中下标为 20 的常量。


第 19 个常量:


#19 = NameAndType        #5:#6          // age:I


类型为 NameAndType,表明是字段或者方法的部分符号引用,指向常量池中下标为 5 和 6 的常量。


第 5 个常量:


#5 = Utf8               age


类型为 Utf8,UTF-8 编码的字符串,值为 age,表明字段名为 age。


第 6 个常量:


#6 = Utf8               I


类型为 Utf8,UTF-8 编码的字符串,值为 I,表明字段的类型为 int。



关于字段类型的描述符映射表如下图所示。


image.png


相关文章
|
6月前
|
安全 Java API
JDK 11中的动态类文件常量:探索Java字节码的灵活性与动态性
在JDK 11中,Java语言引入了一个新的特性,允许在运行时动态地修改类文件常量。这一特性为Java开发者提供了更大的灵活性,使他们能够根据需要在运行时更改类文件中的常量值。本文将深入探讨动态类文件常量的工作原理、优点、限制以及在实际项目中的应用。
151 11
|
10天前
|
Java
轻松上手Java字节码编辑:IDEA插件VisualClassBytes全方位解析
本插件VisualClassBytes可修改class字节码,包括class信息、字段信息、内部类,常量池和方法等。
60 6
|
23天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
23天前
|
Java API Maven
如何使用 Java 字节码工具检查类文件的完整性
本文介绍如何利用Java字节码工具来检测类文件的完整性和有效性,确保类文件未被篡改或损坏,适用于开发和维护阶段的代码质量控制。
|
1月前
|
Java
如何从Java字节码角度分析问题|8月更文挑战
如何从Java字节码角度分析问题|8月更文挑战
|
2月前
|
Arthas Java 测试技术
Java字节码文件、组成,jclasslib插件、阿里arthas工具,Java注解
Java字节码文件、组成、详解、分析;常用工具,jclasslib插件、阿里arthas工具;如何定位线上问题;Java注解
Java字节码文件、组成,jclasslib插件、阿里arthas工具,Java注解
|
6月前
|
设计模式 Java 程序员
【设计模式】JAVA Design Patterns——Bytecode(字节码模式)
【设计模式】JAVA Design Patterns——Bytecode(字节码模式)
|
2月前
|
Java API 开发者
【Java字节码操控新篇章】JDK 22类文件API预览:解锁Java底层的无限可能!
【9月更文挑战第6天】JDK 22的类文件API为Java开发者们打开了一扇通往Java底层世界的大门。通过这个API,我们可以更加深入地理解Java程序的工作原理,实现更加灵活和强大的功能。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来!
|
2月前
|
Java API 开发者
【Java字节码的掌控者】JDK 22类文件API:解锁Java深层次的奥秘,赋能开发者无限可能!
【9月更文挑战第8天】JDK 22类文件API的引入,为Java开发者们打开了一扇通往Java字节码操控新世界的大门。通过这个API,我们可以更加深入地理解Java程序的底层行为,实现更加高效、可靠和创新的Java应用。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来,并积极探索类文件API带来的无限可能!
|
3月前
|
监控 Java API
分布式链路监控系统问题之对Java应用实现字节码增强的方式的问题如何解决
分布式链路监控系统问题之对Java应用实现字节码增强的方式的问题如何解决