1. 程式人生 > >Java堆內存與棧內存對比

Java堆內存與棧內存對比

sin runtime 一段 線程 全局 args public ng- error:

在數據結構中,堆和棧可以說是兩種最基礎的數據結構,而Java中的棧內存空間和堆內存空間有什麽異同,以及和數據結構中的堆棧有何關系?

一、Java 堆存儲空間

堆內存(堆存儲空間)會在Java運行時分配給對象(Object)或者JRE的類。只要我們創建了一個對象,那麽在堆中肯定會分配一塊存儲空間給這個對象。而我們熟知的Java垃圾回收就是在堆存儲空間上進行的,用以釋放那些沒有任何引用指向自身的對象。任何在堆中分配的對象都有全局訪問權限,而且可以從應用的任何地方被引用。

二、Java 棧存儲空間

Java 棧存儲空間用來供線程執行時使用。棧空間中包含特別的變量如:短生命周期和指向其他在堆中對象的引用。這裏棧存儲空間滿足後進先出的順序。當一個函數被調用時,會在棧中分配一塊新的存儲空間,用來存放函數的基本數據(【Java心得總結一】Java基本類型和包裝類型解析)以及在函數中對其它對象的引用。一旦函數執行結束,存儲空間就會被釋放供下一個函數使用。

棧存儲空間遠遠小於堆存儲空間

三、舉例

Memory.java

技術分享圖片
 1 public class Memory {
 2  
 3     public static void main(String[] args) { // Line 1
 4         int i=1; // Line 2
 5         Object obj = new Object(); // Line 3
 6         Memory mem = new Memory(); // Line 4
 7         mem.foo(obj); // Line 5
 8     } // Line 9
 9  
10     private void foo(Object param) { // Line 6
11         String str = param.toString(); //// Line 7
12         System.out.println(str);
13     } // Line 8
14  
15 }
技術分享圖片

下圖展示了堆棧存儲空間是如何存儲基本類型、對象以及指向變量的引用

技術分享圖片

程序執行過程:

  1. 一旦我們開始運行程序,它會將所有運行時類裝載入堆存儲空間。當程序運行至第一行main()函數,Java Runtime會為主函數線程分配棧存儲空間。
  2. 我們在第二行創建了基本數據類型,所以它會被存儲在主函數線程的棧存儲空間;
  3. 因為我們在第三行創建了Object對象,它會在堆中被創建,並且棧空間中保存有指向它的引用。同理第四行創建Memory對象。
  4. 當我們在main()主函數第五行調用foo()函數時,在棧空間頂部會分配一塊空間給foo()函數使用。因為Java是值傳遞(Java 為值傳遞而不是引用傳遞),在foo函數第六行中會有一個新的引用被創建指向堆中的Object對象
  5. 在第7行創建了一個字符串,它會被放在堆空間的字符串池中(String Poll),而且在棧空間中會保存一個指向它的引用
  6. 在第8行foo函數執行完畢,此時其棧空間會被釋放
  7. 在第9行main函數執行完畢,棧中分配給main函數的空間會被釋放。同時程序也在這一行執行完畢,因此Java運行時(Java Runtime)會釋放所有內存空間並且終止程序的執行。

四、堆棧異同

  1. 堆存儲空間可以被應用的任何部分使用,然而棧存儲空間只能被對應的執行線程使用
  2. 一旦對象被建立,那麽就會在堆中分配一段存儲空間而棧空間中保留有對它的引用。棧空間中僅僅保存基本數據類型和指向堆中對象的引用變量
  3. 堆中存儲的對象可以被全局訪問,然而棧中存儲的變量不能被其它線程(函數)訪問
  4. 棧中的內存管理采用先進後出的(LIFO)的方式,然而在堆中內存管理會更為復雜,因為堆中的對象可以被全局使用。對存儲空間被分為Young-Generation,Old-Generation等,這個我會在之後總結
  5. 棧存儲空間是短生命周期的,然而堆存儲要長的多
  6. 利用-Xms和-Xmx來指明JVM的堆初始空間和最大空間,利用-Xss來定義棧空間大小
  7. 當棧空間滿了,Java運行時會拋出 java.lang.StackOverFlowError ,然而堆空間滿了,拋出的是 java.lang.OutOfMemoryError: Java Heap Space 錯誤
  8. 棧空間相比較於堆空間是非常小的,又因為棧中使用最簡單的先進後出(LIFO)原則,它是遠遠快於堆的。

參考:https://www.cnblogs.com/xltcjylove/p/4502859.html

Java堆內存與棧內存對比