Class 文件是 JVM 識別的統一二進制格式,實現了「Write Once, Run Anywhere」的跨平台承諾。無論 Java、Kotlin、Scala、Groovy 還是 JRuby,只要能編譯生成符合規範的 .class 文件,就能在 JVM 上運行。本文深入剖析 Class 文件的偽結構定義、核心組成部分、常量池 14 種表結構、以及使用 javap 進行實戰解析的技巧。

將包名「.」替換為「/」,末尾加「;」。例:java.lang.Object → java/lang/Object;。
方法名/字段名本身,無包前綴。例:toString()。
| 字符 | 類型 |
|---|---|
| B | byte |
| C | char |
| D | double |
| F | float |
| I | int |
| S | short |
| J | long |
| Z | boolean |
| V | void |
| L + 類全限定名 + ; | 對象類型 |
| [ | 數組類型(每維一個 [) |
例:String → Ljava/lang/String;,long[] → [J。
格式:(參數描述符列表)返回值描述符。例:Object m(int i, double d, Thread t) → (IDLjava/lang/Thread;)Ljava/lang/Object;。
ClassFile {
u4 magic; // 魔數 0xCAFEBABE
u2 minor_version; // 次版本號
u2 major_version; // 主版本號
u2 constant_pool_count; // 常量池計數器 (n+1)
cp_info constant_pool[count-1]; // 常量池數據
u2 access_flags; // 訪問標識
u2 this_class; // 當前類索引
u2 super_class; // 父類索引
u2 interfaces_count; // 接口數量
u2 interfaces[interfaces_count]; // 接口索引表
u2 fields_count; // 字段數量
field_info fields[fields_count]; // 字段表
u2 methods_count; // 方法數量
method_info methods[methods_count]; // 方法表
u2 attributes_count; // 屬性數量
attribute_info attributes[attributes_count]; // 屬性表
}
文件大小 = 定長部分(26字節) + 變長表數據總和。
文件頭 4 字節,固定 0xCAFEBABE。同樣原理:JPEG 以 FF D8 FF 開頭,PNG 以 89 50 4E 47 開頭。JVM 加載時首檢魔數,不匹配拋 ClassFormatError。
緊隨魔數 4 字節:minor_version、major_version。高版本 JVM 可向下兼容低版本 Class 文件,反之則拋 UnsupportedClassVersionError。
空間佔用最大、結構最複雜、項目最多的區域。長度不固定,constant_pool_count = n+1(索引 0 保留為「不引用任何常量池項目」)。
每項結構:
cp_info {
u1 tag; // 標識類型 (1~18, JDK 1.7 有 14 種常用)
u1 info[]; // 具體數據
}

CONSTANT_String、CONSTANT_Integer、CONSTANT_Float、CONSTANT_Long、CONSTANT_Double、CONSTANT_Class(類字面量)。CONSTANT_Class_info(類/接口全限定名)、CONSTANT_Fieldref_info(字段名描述符)、CONSTANT_Methodref_info/CONSTANT_InterfaceMethodref_info(方法名描述符)、CONSTANT_NameAndType_info(名稱+描述符)。CONSTANT_Utf8_info:存儲 UTF-8 編碼字符串(類名、方法名、字段名、字面量字符串),其他表項引用它。CONSTANT_MethodHandle_info、CONSTANT_MethodType_info、CONSTANT_InvokeDynamic_info:支撐 invokedynamic、Lambda、MethodHandle。access_flags:標識類/接口層級修飾符。ACC_PUBLIC、ACC_FINAL、ACC_SUPER、ACC_INTERFACE、ACC_ABSTRACT、ACC_SYNTHETIC、ACC_ANNOTATION、ACC_ENUM、ACC_MODULE(JDK 9+)。
this_class、super_class、interfaces[]:均為常量池索引,指向 CONSTANT_Class_info。
結構相似:
field_info / method_info {
u2 access_flags; // 訪問標識
u2 name_index; // 名稱索引 → CONSTANT_Utf8
u2 descriptor_index; // 描述符索引 → CONSTANT_Utf8
u2 attributes_count; // 屬性計數
attribute_info attributes[attributes_count]; // 屬性集合
}
字段屬性:ConstantValue(final 常量值)、Synthetic、Signature(泛型簽名)、Deprecated、RuntimeVisibleAnnotations 等。
方法屬性:Code(字節碼、行號、局部變量表、異常表)、Exceptions、Signature、RuntimeVisibleParameterAnnotations、AnnotationDefault 等。
贯穿 ClassFile、field_info、method_info、Code_attribute。JVM 規範預定義 20+ 種屬性,未識別屬性必須忽略(保證向前兼容)。核心屬性:
Code:方法體字節碼、操作數棧深度、局部變量表、行號表、異常表。ConstantValue:final static 基本類型/String 常量值。SourceFile、SourceDebugExtension:源文件名、擴展調試信息。LineNumberTable、LocalVariableTable:調試關鍵。StackMapTable:類型驗證用(JDK 6+)。BootstrapMethods:invokedynamic 引導方法。# 基本反編譯
javap -c MyClass.class
# 詳細模式(常量池、行號、局部變量、Code 屬性完整輸出)
javap -v -p MyClass.class
# 僅輸出常量池
javap -verbose -constants MyClass.class
# 輸出行號表與局部變量表
javap -l MyClass.class
# 系統信息
javap -sysinfo MyClass.class
結合本文結構定義,可手工驗證每個字節含義,是理解編譯器行為、排查版本衝突、分析字節碼增強框架(ASM/ByteBuddy)生成代碼的核心技能。
Class 文件以緊湊二進制流、偽結構定義、豐富常量池、屬性表擴展機制,構建了 JVM 跨語言、跨平台、可擴展的二進制契約。掌握其結構,是深入 JVM 原理、字節碼編程、框架底層開發的必經之路。