首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 數組內存分配深度解析:引用變量、堆棧交互與 GC 行為

     編輯:Java 相關知識

核心誤區澄清

「基本類型在棧,對象在堆」不完全正確。更精確的描述:

  • 局部變量(基本類型 + 引用變量) 存放在棧幀中。
  • 對象實例(包括數組、String、自定義類) 存放在堆中。
  • 引用變量指向堆中對象,通過引用訪問對象屬性/方法時,才真正成為「對象操作」。

數組變量 vs 數組對象

String[] names = {"Michael", "Orson", "Andrew"}; // names: 棧上引用 → 堆上 String[3] 對象
String[] animal = new String[4];                // animal: 棧上引用 → 堆上 String[4] 對象
names = animal; // names 引用指向 animal 所指對象,原 String[3] 變為垃圾
System.out.println(names.length); // 4
System.out.println(animal.length); // 4

關鍵點:數組大小不可變,但引用變量可指向不同大小的數組對象。賦值只是複製引用,不複製對象。

圖解內存結構

賦值前後引用指向變化

  • 藍虛線:賦值前 names 指向長度 3 數組,animal 指向長度 4 數組。
  • 紅實線:賦值後兩引用共指長度 4 數組;長度 3 數組無引用,待 GC 回收。

基本類型值也在堆?

String[] arr = {"Michael", "Orson"}; // "Michael" 是 String 對象,在堆
// 字面量 "Michael" 在常量池(堆的一部分),arr[0] 引用指向它

基本類型局部變量(如 int age = 10;)確在棚;但作為對象字段或數組元素時,隨對象在堆。

對象「誕生」時刻


class Animal { String name; int age; }
Animal[] animals = new Animal[2]; // animals: 引用 → 堆 Animal[2](元素均 null)
Animal cat = new Animal("cat", 1); // cat: 引用 → 堆 Animal 對象
Animal dog = new Animal("dog", 2);
animals[0] = dog; // animals[0] 引用指向 dog 所指對象
animals[1] = cat;
dog.info();       // dog 引用調用方法 → 真正操作堆上對象
animals[0].info(); // 同一對象,輸出相同

數組元素指向對象

  • 只有當引用變量調用方法/訪問字段時,才發生真正的對象操作(解引用)。
  • 賦值 animals[0] = dog 只是複製引用,不創建新對象。

GC 根與回收

  • 棧上引用是 GC Root,可達性分析起點。
  • names = animal 後,原 String[3] 無 GC Root 可達,下次 GC 回收。
  • 循環引用(A→B→A)若無 GC Root 可達,同樣可被回收(JDK 1.2+ 採用可達性分析)。

實戰啟示

  1. 大數組、大對象避免頻繁賦值導致舊對象堆積,增加 GC 壓力。
  2. 集合類(ArrayList 等)內部封裝數組,擴容本質是新建數組+複製引用,同理。
  3. 方法參數傳遞是值傳遞:基本類型傳值,引用類型傳引用值(地址),無法在方法內改變實參引用指向。
  4. 使用 -Xmx -Xms 設定堆大小,配合 -XX:+PrintGCDetails 觀察數組分配回收行為。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved