Java .class 檔案是 JVM 執行的基本單位,採用 8 位元組為基礎的二進位格式。本文從 JVM 規範角度剖析 Class 檔案結構,並說明 java.lang.Class 執行時反射應用。
forName() 動態載入、newInstance() 反射實例化、getClassLoader()、getSuperclass()、getDeclaredMethods()、getConstructors() 等。ClassFile {
u4 magic; // 魔數 0xCAFEBABE
u2 minor_version;
u2 major_version; // 版本號(JDK 7 = 51)
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[]; // 屬性表集合
}
0xCAFEBABE 識別合法 class 檔。tag 識別型別(如 CONSTANT_Utf8=1、CONSTANT_Class=7、CONSTANT_Methodref=10 等)。ACC_PUBLIC=0x0001、ACC_FINAL=0x0010、ACC_SUPER=0x0020、ACC_INTERFACE=0x0200、ACC_ABSTRACT=0x0400 等位元組合。access_flags、name_index、descriptor_index、attributes。描述符範例:I(int)、[Ljava/lang/String;(String[])。Code 屬性(位元碼指令、操作數堆疊深度 max_stack、區域變數表 max_locals、例外表、LineNumberTable、LocalVariableTable)。public int interB(int i) {
int x = 0;
try { x = i + 1; return x; }
catch (Exception e) { return -1; }
finally { x = 2; }
}
反編譯位元碼顯示三條執行路徑(正常、捕獲 Exception、捕獲其他),對應例外表 from/to/target/type。LineNumberTable 對應原始碼行號,LocalVariableTable 記錄區域變數槽位(this 佔 slot 0,參數 i 佔 slot 1,編譯器自動插入 this)。
保留泛型簽名資訊(型別變數、參數化型別),供反射取得實際泛型參數,如 Hibernate DAO 基類透過 TypeVariable 解析實體類別。
Class> clazz = Class.forName("com.example.User");
Object obj = clazz.newInstance();
Method m = clazz.getMethod("setName", String.class);
m.invoke(obj, "Alice");
掌握 Class 檔案結構與反射 API,有助於框架開發、動態代理、序列化庫等進階應用。