Java 堆棧內存分配

不少人在Java的書籍中看到過不少關於堆和棧內存的教程以及參考說明, 可是很難解釋什麼是程序的堆內存以及棧內存java

一: Java 堆內存空間jvm

Java程序運行時使用java Heap 內存爲對象以及JRE類分配內存, 不論咱們在什麼時候建立何種類型的對象, 他老是在堆內存中建立的函數

Java 垃圾收集器運行在堆內容空間, 釋放那些沒有任何引用的對象所使用的內存。 在堆內存空間建立的任何對象都具備全局訪問權限, 而且能夠從程序的任何位置引用this

二: Java 棧內存空間spa

Java 棧內存空間用於執行線程, 棧內存始終遵循LIFO(Last-in-first-out) 順序, 每當一個方法被執行, 會在棧內存中建立一個新的block 用於保存在函數中定義的基本數據類型變量以及對象的引用變量線程

當方法結束時, this block 改變它的狀態爲未使用而且可用於執行下一個方法code

堆內存大小與堆內存相比很是少。cdn

三: Java程序中的堆和堆棧內存對象

經過一個簡單的程序來理解堆 棧內存的使用狀況blog

/** * Created by huanjulu on 12/10/17. */

public class HeapStackTestMemory {

    public static void main(String[] args) { //Line 1

        int i = 1; //Line 2

        Object obj = new Object(); //Line 3

        HeapStackTestMemory mem = new HeapStackTestMemory(); //Line 4

        mem.foo(obj);  //Line 5

    }  //Line 9

    private void foo(Object param) {  //Line 6

        String str = param.toString();  //Line 7

        System.out.println(str);

    } //Line 8

}複製代碼

參考上面的java 程序, 下圖顯示了stack Heap 內存空間的使用狀況

咱們來看看執行程序的步驟。

  • 一旦咱們開始運行程序, 它會把全部的運行時類加載到堆內存空間, 在 Line 1 行找到main() 方法, Java Runtime 建立由main() 方法線程使用的棧內存空間
  • 在第二行 咱們建立了原始數據類型的局部變量, 因此它將被存儲在main() 方法的棧內存空間
  • 在第3行咱們建立了一個Object 類型的對象, 因此它被建立在Heap 堆內存空間中 而且 Stack 棧內存空間包含對它的引用, 當咱們在第4行中建立Memory 對象時, 會發生相似的過程
  • 如今咱們在第5行調用foo() 方法, 此時會在stack 棧建立一個block 供foo() 方法使用
  • Java 是經過值傳遞, 在第6行, 會在foo() 棧中建立一個對Object 對象的新的引用
  • 在第7行 , 一個string 類型的對象被建立, 此時 會在foo() 棧內存中建立它的一個引用 str
  • foo() 方法在第8行執行完畢, 此時, 程序會釋放stack 棧內存中爲foo() 方法分配的棧內存空間
  • 在第9行, main() 方法執行完畢, 爲main()方法建立的堆棧內存被銷燬, 此時 這個java 程序結束運行, Java Runtime 會釋放全部的內存

 
三: Java Heap Difference with Stack Memory Space

基於上述的說明, 能夠很容易的總結出堆棧內存的如下差別

1, 堆內存屬於java 應用程序所使用, 棧內存屬於線程所私有的, 它的生命週期與線程相同2, 不論什麼時候建立一個對象, 它老是存儲在堆內存空間 而且棧內存空間包含對它的引用 . 棧內存空間只包含方法原始數據類型局部變量以及堆空間中對象的引用變量3, 在堆中的對象能夠全局訪問, 棧內存空間屬於線程所私有4, jvm 棧內存結構管理較爲簡單, 遵循LIFO 的原則, 堆空間內存管理較爲複雜 , 細分爲:新生代和老年代 etc..5, 棧內存生命週期短暫, 而堆內存伴隨整個用用程序的生命週期6, 兩者拋出異常的方式, 若是線程請求的棧深度大於虛擬機所容許的深度,將拋出StackOverflowError異常, 堆內存拋出OutOfMemoryError異常

相關文章
相關標籤/搜索