A a = new A(); 在堆中分配 A 實例,棧上變量 a 存儲**引用(地址)**。
若 A 類包含 String name; 字段,則 A 實例內部存儲 name 字段的**引用**,指向堆中(或常量池中)獨立的 String 對象。
棧帧 (main)
+-----------------+
| a (引用) ──────┼──▶ 堆
+-----------------+ +---------------------+
| A 實例 |
| +-----------------+ |
| | name (引用) ───┼───▶ 堆/常量池
| | other fields... | | +---------------------+
| +-----------------+ | | String "Hello" |
+---------------------+ | char[] value [...] |
| int hash = ... |
+---------------------+
"Hello" → **字符串常量池**(方法區/元空間,JDK 7+ 在堆)。new String("Hello") / 運行時拼接 → **堆**。-XX:+UseCompressedOops),引用佔 **4 字節**;關閉時 8 字節。Mark Word (8/16 字節) + Klass Pointer (4/8 字節),數組額外有長度字段。long/double 8 字節對齊,int/float 4 字節,引用 4/8 字節,boolean/byte 1 字節),非 @Contended 時不保證聲明順序。<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.16</version>
</dependency>
public class Demo {
static class A { String name; int age; }
public static void main(String[] args) {
A a = new A(); a.name = "Hello"; a.age = 25;
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
// 輸出示例:
// A object internals:
// OFFSET SIZE TYPE DESCRIPTION
// 0 12 (object header)
// 12 4 String A.name ← 引用,4字節
// 16 4 int A.age
// 20 4 (alignment padding)
// Instance size: 24 bytes
record/value class 預覽特性),**只有引用**。new String()、substring() (JDK 7+)、拼接結果在堆。理解「引用鏈:棧變量 → 堆對象 → 引用字段 → 另一堆對象/常量池」,是排查 OOM、優化內存佔用、分析 JOL 輸出的基石。