Class 文件是 JVM 執行的基礎單元,採用 8 位字節為基礎單位的二進制流,嚴格按順序緊湊排列,無分隔符。本文系統梳理 Class 文件格式、數據類型、各項結構及實戰分析方法。
u1(1字節)、u2(2字節)、u4(4字節)、u8(8字節),用於數字、索引、數量、UTF-8 字符串。_info 結尾。整個 Class 文件本質上就是一張表。ClassFile {
u4 magic; // 魔數 0xCAFEBABE
u2 minor_version; // 次版本號
u2 major_version; // 主版本號
u2 constant_pool_count;// 常量池計數器
cp_info constant_pool[]; // 常量池表
u2 access_flags; // 訪問標志
u2 this_class; // 類索引
u2 super_class; // 父類索引
u2 interfaces_count; // 接口計數器
u2 interfaces[]; // 接口索引集合
u2 fields_count; // 字段計數器
field_info fields[]; // 字段表集合
u2 methods_count; // 方法計數器
method_info methods[]; // 方法表集合
u2 attributes_count; // 屬性計數器
attribute_info attributes[]; // 屬性表集合
}
識別 Class 文件格式,防止誤加載非 Class 文件。
JVM 向下兼容(高版本 JVM 可運行低版本 Class),不向上兼容。主版本號對應 Java 版本(如 52 = Java 8, 55 = Java 11, 61 = Java 17)。
計數器:constant_pool_count = 條目數 + 1(索引 0 保留,表示「無引用」)。
內容分類:
final 常量值、基本類型值。14 種常量表類型(tag 值 1-18,部分保留):Utf8, Integer, Float, Long, Double, Class, String, Fieldref, Methodref, InterfaceMethodref, NameAndType, MethodHandle, MethodType, InvokeDynamic。
標識類/接口屬性:ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE。
this_class:指向 CONSTANT_Class_info,再指向 CONSTANT_Utf8_info 獲取全限定名。super_class:同理,java.lang.Object 除外均不為 0。interfaces[]:實現的接口列表。field_info 結構:
access_flags (2字節) name_index (2字節) // 指向 CONSTANT_Utf8_info descriptor_index (2字節) // 指向 CONSTANT_Utf8_info,描述符如 "I", "Ljava/lang/String;" attributes_count (2字節) attributes[] // ConstantValue, Deprecated, Synthetic 等
不包含局部變量(方法內變量)。
method_info 結構:
access_flags (2字節) name_index (2字節) descriptor_index (2字節) // 如 "()V", "(II)I", "([CII[CIII)I" attributes_count (2字節) attributes[] // Code, Deprecated, Exceptions, Synthetic
描述符規則:
B, C, D, F, I, J, S, Z, V。L全限定名;(如 Ljava/lang/String;)。[(如 [[I, [Ljava/lang/Object;)。(參數描述符)返回描述符。javap -verbose ClassName:標準反編譯,輸出人類可讀結構。javap -c ClassName:顯示字節碼指令。掌握 Class 文件結構,是理解類加載機制、字節碼增強、動態代理、框架原理(Spring ASM、Lambda 元工廠)的基石。