深入JVM(二):字节码文件的结构

字节码文件的结构

一、源代码

java 复制代码
package p_05_class_structure;

/**
 * @author dyl
 * @version 1.0
 * @description:
 * @date 2025/12/14 18:02
 */
public class ByteCode {

    private String username;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

二、编译和反编译

首先到控制台编译类文件:

cmd 复制代码
cd E:\xxx\01-JVM-01\src
javac p_05_class_structure\ByteCode.java

然后进行反编译查看class文件反编译详情

cmd 复制代码
javap -verbose p_05_class_structure.ByteCode

详情结果:

cmd 复制代码
  // 表示反编译的来源是哪个字节码文件
Classfile /E:/xxx/src/p_05_class_structure/ByteCode.class
  // 最后修改日期和文件大小
  Last modified 2025年12月14日; size 427 bytes
  // 文件的sha-256值
  SHA-256 checksum fe213f3ed1a1c25941d6e19e5a79443395eb752c846bc38948c245ceb8963312
  // 编译源文件
  Compiled from "ByteCode.java"
// 字节码详细信息
public class p_05_class_structure.ByteCode
  // jdk次版本号
  minor version: 0
  // jdk主版本号(52是jdk8,53是9,以此类推,61是jdk17)
  major version: 61
  // 访问权限
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #8                          // p_05_class_structure/ByteCode
  super_class: #2                         // java/lang/Object
  interfaces: 0, fields: 1, methods: 3, attributes: 1
// 常量池
Constant pool:
   #1 = Methodref          #2.#3          // java/lang/Object."<init>":()V
   #2 = Class              #4             // java/lang/Object
   #3 = NameAndType        #5:#6          // "<init>":()V
   #4 = Utf8               java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Fieldref           #8.#9          // p_05_class_structure/ByteCode.username:Ljava/lang/String;
   #8 = Class              #10            // p_05_class_structure/ByteCode
   #9 = NameAndType        #11:#12        // username:Ljava/lang/String;
  #10 = Utf8               p_05_class_structure/ByteCode
  #11 = Utf8               username
  #12 = Utf8               Ljava/lang/String;
  #13 = Utf8               Code
  #14 = Utf8               LineNumberTable
  #15 = Utf8               getUsername
  #16 = Utf8               ()Ljava/lang/String;
  #17 = Utf8               setUsername
  #18 = Utf8               (Ljava/lang/String;)V
  #19 = Utf8               SourceFile
  #20 = Utf8               ByteCode.java
{
  // 构造方法
  public p_05_class_structure.ByteCode();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 9: 0
  // get方法
  public java.lang.String getUsername();
    descriptor: ()Ljava/lang/String;
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #7                  // Field username:Ljava/lang/String;
         4: areturn
      LineNumberTable:
        line 14: 0
  // set方法
  public void setUsername(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: putfield      #7                  // Field username:Ljava/lang/String;
         5: return
      LineNumberTable:
        line 18: 0
        line 19: 5
}
SourceFile: "ByteCode.java"

三、通过打开class文件查看十六进制的信息

class文件的结构

结构刨析(以上面字节码class文件为例):

  1. 魔数:4字节 CA FE BA BE

  2. 次版本号:2字节 00 00 (0)

  3. 主版本号:2字节 00 3d (62:jdk17)

  4. 常量个数:2字节 00 15 (21-1:class文件反编译内容中是20个常量,外加jvm占用0号常量(null))

  5. 常量池表:N字节

  • 常量1:0a(标记)00 02(常量池索引为2的常量(class文件反编译中为#2:java/lang/Object)) 00 03 (常量池第3号常量("<init>"😦)V))

  • 常量2:07(标记) 00 04(常量池4号:java/lang/Object)

  • 常量3: 0c(标记) 00 05(name_index:<init>) 00 06 (descriptor_index: ()V)

  • 常量4:01(标记) 00 10(长度:16,后面数16个字节) 6a 61 76 61 2f 6c 61 6e 67 2f 4f 62 6a 65 63 74(bytes: 字符串:"java/lang/Object")

  • 。。。。。。

  1. 访问标记符号:2字节 (一般是复合型:例如0x02001 表示0x0001(public)+0x0200(接口))

  2. class name (2字节)

  3. super class name (2字节)

  4. 接口数(2字节)(所以一个类的接口数量不可以超过65535)

  5. 字段数(2字节)

  6. 字段表(对象,里面包含每个字段的信息)

  7. 方法个数(2字节)

  8. 方法表 / 附加属性表

    其中包含一些栈深度、指令长度、字节码代码和源文件代码的映射表(这也是为什么java执行的是字节码文件为什么报错的时候可以知道在代码中是多少行报错)、==本地变量表(本地变量表在编译的时候就已经确定)==等

相关推荐
DN金猿几秒前
接口路径正确,请求接口却提示404
java·tomcat
毕设源码-郭学长1 分钟前
【开题答辩全过程】以 基于python的二手房数据分析与可视化为例,包含答辩的问题和答案
开发语言·python·数据分析
无小道24 分钟前
Qt——常用控件
开发语言·qt
爱学习的阿磊32 分钟前
使用Fabric自动化你的部署流程
jvm·数据库·python
Maynor99641 分钟前
OpenClaw 玩家必备:用 AI 自动追踪社区最新动态
java·服务器·人工智能
aini_lovee41 分钟前
MATLAB基于小波技术的图像融合实现
开发语言·人工智能·matlab
堕2741 小时前
java数据结构当中的《排序》(一 )
java·数据结构·排序算法
R1nG8631 小时前
多线程安全设计 CANN Runtime关键数据结构的锁优化
开发语言·cann
m0_550024631 小时前
持续集成/持续部署(CI/CD) for Python
jvm·数据库·python
初次见面我叫泰隆1 小时前
Qt——5、Qt系统相关
开发语言·qt·客户端开发