Java 內存模型中「對象在堆、引用在棧」的說法雖普遍,但對「實例變量包含引用」的初學者極易產生矛盾感。本文從變量聲明位置(局部 vs 成員)徹底釐清存儲歸屬。
| 變量類型 | 聲明位置 | 引用/值本身存儲 | 引用指向的對象存儲 |
|---|---|---|---|
| 基本類型 | 方法內(局部) | 棧 | — |
| 引用類型 | 方法內(局部) | 棧 | 堆 |
| 基本類型 | 類內(成員/實例變量) | 堆(隨對象) | — |
| 引用類型 | 類內(成員/實例變量) | 堆(隨對象) | 堆 |
new 出來的對象(含其所有實例字段)分配在堆上。Class 對象中。class User {
String name; // 實例引用變量 → 槽位在堆(User 對象內)
int age; // 實例基本變量 → 槽位在堆(User 對象內)
}
void method() {
User u = new User(); // u 是局部引用變量 → 槽位在棧
// new User() 對象實體 → 在堆
String local = "x"; // local 局部引用 → 棧槽位指向堆/常量池字符串
}
jvisualvm / arthas 觀察堆快照,實例字段隨對象共存。-XX:+PrintEscapeAnalysis 查看標量替換優化(逃逸分析可將未逃逸對象標量化拆解到棧)。掌握「對象在堆、變量槽位隨聲明位置」這一核心模型,即可輕鬆解決所有堆棧存儲疑惑。