🗒️JVM第一课:class文件结构
2024-2-27
| 2024-3-1
0  |  阅读时长 0 分钟
tags
type
status
date
slug
summary
category
password
icon
😀
本文以 JDK8为例,讲解 Class 文件结构。
 
JDK 文档官网:docs.oracle.com/javase/8/

前言

Oracle 有两个产品实现了 Java SE (Java Platform Standard Edition) 8,分别为Java SE Development Kit (JDK) 8和 Java SE Runtime Environment (JRE) 8。
JDK 8是 JRE 8的超集,包含 JRE 8中的所有内容,以及开发 applet 和应用程序所需的编译器和调试器等工具。
而 JRE 8提供库、Java 虚拟机(JVM)和其他组件来运行用 Java 编程语言编写的 applet 和应用程序。请注意,JRE 包括 Java SE 规范不需要的组件,包括标准组件和非标准组件。
简而言之,JDK 适用于开发,JRE 仅仅适用于 applet 和应用程序的部署运行,及在服务器环境下可以只使用 JRE。
notion image

class 文件的产生

  • .class 文件是 .java 文件编译后的形成的中间文件。下面使用一个小例子来看一下 class 文件的结构。
例:我们有以下的源代码文件—— Main.java
编译 javac Main.java ---> Main.class
补充点编译细节:Main.java -> 词法分析器 -> tokens 流 -> 语法分析器 -> 语法树/抽象语法树 -> 语义分析器 -> 注解抽象语法树 -> 字节码生成器 -> Main.class 文件。这里就不展开细说啦。
经过编译后,我们得到了 Main.class 文件,如果要打开这个文件我们会看到一串一串字符乱码,这些字符是无法直接取阅读的。通过反编译后,就可以得到类似于源码的代码,如下。
补充:反编译工具
  1. javap
  1. IDE 工具:如 Idea 工具栏中 View---'show bytecode'。
  1. Idea 插件—— jclasslib Bytecode Viewer,最直观展示信息。
javap 是 Java 开发工具包(JDK)提供的一个命令行工具,用于反编译 Java 字节码。javap 可以将 Java 类文件解析为易于阅读的文本形式,展示其中的信息以及反编译出类的结构、方法、字段、常量池等信息。通过阅读和分析这些信息,开发人员可以更好地理解 Java 类的内部实现,并进行性能调优、代码审查等操作。
我们可以使用 jclasslib Bytecode Viewer 插件,直观的阅读 class 文件结构,包括 class 文件格式的主次版本号、常量池等信息。
notion image

class 文件结构介绍

每个 class 文件包含一个类或接口的定义。
类文件由字节流组成,既我们所看到的一串一串字符。所有 16 位、32 位和 64 位的变量也都是通过读入 2 个、4 个和 8 个连续的字节构建的。并且多字节数据项总是按大端模式存储,即高字节位在前。
如下是 oracle 官方给的 class 文件结构
案例中的数据类型表示为 u1u2u4 类型分别代表一个、两个或四个字节的无符号量,这些类型可通过 java. Io. DataInput 接口的 readUnsignedByte、readUnsignedShort 和 readInt 等方法读取。
下面介绍下 class 文件结构的具体含义。
类型
名称
数量
说明
u4
magic
1
魔数:确定一个文件是否是 Class 文件。值是固定的为 0xCAFEBABE
u2
minor\_version
1
Class 文件的次版本号,与主版本号共同决定 class 文件格式的版本。如果一个类文件的主要版本号为 M,次要版本号为 m,我们就用 M.m 表示其类文件格式的版本。
u2
major\_version
1
Class 文件的主版本号:一个 JVM 实例只能支持特定范围内版本号的 Class 文件(可以向下兼容)。
u2
constant\_pool\_count
1
常量表数量,constant\_pool\_count 项的值等于 constant\_pool 表中的条目数加1。如果一个常量大于0且小于 constant\_pool\_count 则被认为是有效的。
cp\_info
constant\_pool
constant\_pool\_count-1
常量池:可以理解为 Class 文件的资源仓库,表示在ClassFile结构及其子结构中引用的各种字符串常量、类和接口名、字段名和其他常量。后面的其他数据项可以引用常量池内容。
u2
access\_flags
1
类的访问标志信息:用于表示这个类或者接口的访问权限及基础属性。
u2
this\_class
1
指向当前类的常量索引:用来确定这个类的的全限定名。
u2
super\_class
1
指向父类的常量的索引:用来确定这个类的父类的全限定名。
u2
interfaces\_count
1
接口的数量
u2
interfaces
interfaces\_count
指向接口的常量索引:用来描述这个类实现了哪些接口。
u2
fields\_count
1
字段表数量
field\_info
fields
fields\_count
字段表集合:描述当前类或接口声明的所有字段。
u2
methods\_count
1
方法表数量
method\_info
methods
methods\_count
方法表集合:只描述当前类或接口中声明的方法,不包括从父类或父接口继承的方法。
u2
attributes\_count
1
属性表数量
attributes\_info
attributes
attributes\_count
属性表集合:用于描述某些场景专有的信息,如字节码的指令信息等等。
JVM系列:垃圾回收器(GC)GitHub Action 定时任务执行时区处理
目录