Java——堆棧

Java中的堆棧

一. 解釋

棧(stack)與堆(heap)都是Java用來在Ram中存放數據的地方。Java自動管理棧和堆,程序員不能直接地設置棧或堆。html

1. 棧:

  • 理解:java

    • 棧是操做系統在創建某個進程或者線程(在支持多線程的操做系統中是線程)爲這個線程創建的存儲區域,該區域具備先進後出的特性。程序員

    • 棧內存用來存儲局部變量和方法調用(其實這算是實際運行時JVM提供的性能優化)數組

    //若是該局部變量是基本數據類型,那麼直接將該值存儲在棧中
    int a=1;
    
    //若是該局部變量是一個對象,那麼將引用存在棧中,而對象{1,2}存儲在堆內
    int[] array=new int[]{1,2};

    java中的基本數據類型必定存儲在棧中的嗎?性能優化

  • 特色:多線程

    1). 存取速度比堆要快(不明顯),僅次於直接位於CPU中的寄存器。
    
      2). 棧中的數據能夠共享(也就是說,棧中的數據能夠被多個變量共同引用)
  • 缺點:存在棧中的數據大小與生存期必須是肯定的,缺少靈活性jvm

  • 異常錯誤:若是棧內存沒有可用的空間存儲方法調用和局部變量,JVM會拋出java.lang.StackOverFlowError。性能

2. 堆:

  • 理解:
    • 每一個Java應用都惟一對應一個JVM實例,每個JVM實力惟一對應一個堆。優化

    • 應用程序在運行中所建立的全部類實例都放在這個堆中,並有應用全部的線程共享。操作系統

    • Java中分配堆內存是自動初始化的,Java中全部對象的存儲空間都是在堆中分配的,但這些對象的引用則是在棧中分配的,也就是說,通常創建一個對象是,堆和棧都會分配內存

  • 特色:能夠動態的分配內存大小,生存期也沒必要實現告訴編譯器,在堆中分配的內存,有Java虛擬機的垃圾收集器(GC)來管理。

  • 缺點:因爲要在運行時動態分配內存,存取速度較慢

  • 異常錯誤:而若是是堆內存沒有可用的空間存儲生成的對象,JVM會拋出java.lang.OutOfMemoryError。

3. 關係

在堆中產生了一個數組或對象後,還能夠在棧中定義一個特殊的變量,讓棧中這個變量的取值等於數組或對象在堆內存中的首地址,棧中的這個變量結成了數組或對象的引用變量。

引用變量就至關因而爲數組或對象起的一個名稱,之後就能夠在程序中使用棧中的引用變量來訪問堆中的數組或對象。

引用變量就是普通變量,定義時在棧中分配內存,引用變量在程序運行到做用域外釋放。而數組或對象自己在堆中分配,即便程序運行到使用new產生數組或對象的語句以外,他佔用的堆內存也不會被釋放。

也就是說,數組和對象在沒有引用變量指向它的時候,才變成垃圾,不能在被使用,但這時依然佔用這內存,以後會在一個不肯定的時間唄垃圾回收器釋放掉。

二. Java數據存儲

速度依次遞減

1. 寄存器(register):

這是最快的存儲區,由於它位於不一樣與其餘存儲區的地方——處理器內部。可是寄存器的數量極其有限,因此寄存器由編譯器根據需求進行分配。你不能直接控制,也不能在程序中感受寄存器存在的任何跡象

2. 棧(stack):

位於通用RAM中,但經過他的「堆棧指針」能夠從處理器那裏得到支持。
堆棧指針若向下移動,則分配新的內存;若向上移動,則釋放那些內存。這是一種快速有效的分配存儲方式,僅次於寄存器。
建立程序的時候,Java編譯器必須知道存儲在堆棧內全部數據的確切大小和生命週期,由於它必須生成相應的代碼,以便上下移動堆棧指針。這一約束限制了程序的靈活性,因此雖然某些Java數據存儲在棧內存中(特別是對象引用),可是Java的對象不存儲其中。

3. 堆(heap):

一種通用型內存池,也位於RAM中,用於存放Java對象。
堆不一樣於棧的好處是,編譯器不須要知道要從堆裏分配多少存儲空間,也不須要知道存儲的數據在堆裏存活多長時間,所以,在對立分配存儲有很大的靈活性。

當你建立一個對象時,會自動在對立進行存儲分配。但堆進行存儲分配會比用棧進行存儲須要更多的時間

4. 靜態存儲(static storage):

這裏的靜態是指「在固定的位置」,也是位於RAM,靜態存儲裏存放程序運行時一直存在的數據。可用static關鍵字來標識一個對象的特定元素時靜態的,但對象自己時不會存放在靜態存儲空間的。

5. 常量存儲(constant storage):

常量一般直接置於程序代碼內部。由於他們永遠都不會改變,有的常量須要嚴格的保護,因此能夠將他們置於只讀存儲器中。

6. 非RAM存儲:

若是數據徹底存活於程序以外,那麼他能夠不受程序的任何控制,甚至在程序沒有運行時也能夠存在。

三. JVM的內存分區

1. 棧區:

  • 每一個線程包含本身的一個棧區,棧中只保存局部變量和方法調用。

  • 每一個棧的數據都是私有的,其餘棧不可訪問。

  • 棧 = 基本類型變量區 + 執行環境上下文 + 操做指令區(存放操做指令)

2. 堆區:

  • 存儲的是對象,每一個對象都包含一個與之對應的class信息(Clazz.getClass())獲取,class的目的是獲得操做指令。

  • JVM只有一個堆區,被全部線程共享,堆中只存放對象自己

3. 方法區:

  • 又稱靜態區,被全部線程共享,

  • 方法去包含全部的class和static變量

相關文章
相關標籤/搜索