Java堆和棧的區別和介紹以及JVM的堆和棧

1、Java的堆內存和棧內存

Java把內存劃分紅兩種:一種是堆內存,一種是棧內存。html

堆:主要用於存儲實例化的對象,數組。由JVM動態分配內存空間。一個JVM只有一個堆內存,線程是能夠共享數據的。java

棧:主要用於存儲局部變量和對象的引用變量,每一個線程都會有一個獨立的棧空間,因此線程之間是不共享數據的。程序員

在函數中定義的一些基本類型的變量和對象的引用變量都在函數的棧內存中分配。 當在一段代碼塊定義一個變量時,Java就在棧中爲這個變量分配內存空間,當超過變量的做用域後,Java會自動釋放掉爲該變量所分配的內存空間,該內存空間能夠當即被另做他用。面試

堆內存用來存放由new建立的對象和數組。
在堆中分配的內存,由Java虛擬機的自動垃圾回收器來管理。算法

2、棧與堆的共同點和優缺點

  1. 棧(stack)與堆(heap)都是Java用來在Ram中存放數據的地方。與C++不一樣,Java自動管理棧和堆,程序員不能直接地設置棧或堆。
  2. 棧的優點是,存取速度比堆要快,僅次於直接位於CPU中的寄存器。但缺點是,存在棧中的數據大小與生存期必須是肯定的,缺少靈活性。另外,棧數據能夠共享,詳見第3點。堆的優點是能夠動態地分配內存大小,生存期也沒必要事先告訴編譯器,Java的垃圾收集器會自動收走這些再也不使用的數據。但缺點是,因爲要在運行時動態分配內存,存取速度較慢。
  3. Java中的數據類型有兩種。

一種是基本類型(primitive types), 共有8種,即int, short, long, byte, float, double, boolean, char(注意,並無string的基本類型)。這種類型的定義是經過諸如int a = 3; long b = 255L;的形式來定義的,稱爲自動變量。值得注意的是,自動變量存的是字面值,不是類的實例,即不是類的引用,這裏並無類的存在。如int a = 3; 這裏的a是一個指向int類型的引用,指向3這個字面值。這些字面值的數據,因爲大小可知,生存期可知(這些字面值固定定義在某個程序塊裏面,程序塊退出後,字段值就消失了),出於追求速度的緣由,就存在於棧中。數組

棧有一個很重要的特殊性,就是存在棧中的數據能夠共享。多線程

假設咱們同時定義
int a = 3; int b = 3;
編譯器先處理int a = 3;首先它會在棧中建立一個變量爲a的引用,而後查找有沒有字面值爲3的地址,沒找到,就開闢一個存放3這個字面值的地址,而後將a指向3的地址。接着處理int b = 3;在建立完b的引用變量後,因爲在棧中已經有3這個字面值,便將b直接指向3的地址。這樣,就出現了a與b同時均指向3的狀況。函數

特別注意的是,這種字面值的引用與類對象的引用不一樣。假定兩個類對象的引用同時指向一個對象,若是一個對象引用變量修改了這個對象的內部狀態,那麼另外一個對象引用變量也即刻反映出這個變化。相反,經過字面值的引用來修改其值,不會致使另外一個指向此字面值的引用的值也跟着改變的狀況。如上例,咱們定義完a與 b的值後,再令a=4;那麼,b不會等於4,仍是等於3。在編譯器內部,遇到a=4;時,它就會從新搜索棧中是否有4的字面值,若是沒有,從新開闢地址存放4的值;若是已經有了,則直接將a指向這個地址。所以a值的改變不會影響到b的值。性能

另外一種是包裝類數據,如Integer, String, Double等將相應的基本數據類型包裝起來的類。這些類數據所有存在於堆中,Java用new()語句來顯式地告訴編譯器,在運行時才根據須要動態建立,所以比較靈活,但缺點是要佔用更多的時間。上海尚學堂java培訓。學習

3、Java堆和棧的區別

java中堆和棧的區別天然是面試中的常見問題,下面幾點就是其具體的區別

一、各司其職

最主要的區別就是棧內存用來存儲局部變量和方法調用。而堆內存用來存儲Java中的對象。不管是成員變量,局部變量,仍是類變量,它們指向的對象都存儲在堆內存中。

二、獨有仍是共享

棧內存歸屬於單個線程,每一個線程都會有一個棧內存,其存儲的變量只能在其所屬線程中可見,即棧內存能夠理解成線程的私有內存。而堆內存中的對象對全部線程可見。堆內存中的對象能夠被全部線程訪問。

三、異常錯誤

若是棧內存沒有可用的空間存儲方法調用和局部變量,JVM會拋出java.lang.StackOverFlowError。
而若是是堆內存沒有可用的空間存儲生成的對象,JVM會拋出java.lang.OutOfMemoryError。

四、空間大小

棧的內存要遠遠小於堆內存,若是你使用遞歸的話,那麼你的棧很快就會充滿。若是遞歸沒有及時跳出,極可能發生StackOverFlowError問題。

你能夠經過-Xss選項設置棧內存的大小。-Xms選項能夠設置堆的開始時的大小,-Xmx選項能夠設置堆的最大值。

這就是Java中堆和棧的區別。理解好這個問題的話,能夠對你解決開發中的問題,分析堆內存和棧內存使用,甚至性能調優都有幫助。

4、JVM中的堆和棧

JVM是基於堆棧的虛擬機.JVM爲每一個新建立的線程都分配一個堆棧.也就是說,對於一個Java程序來講,它的運行就是經過對堆棧的操做來完成的。堆棧以幀爲單位保存線程的狀態。JVM對堆棧只進行兩種操做:以幀爲單位的壓棧和出棧操做。 咱們知道,某個線程正在執行的方法稱爲此線程的當前方法.咱們可能不知道,當前方法使用的幀稱爲當前幀。當線程激活一個Java方法,JVM就會在線程的 Java堆棧裏新壓入一個幀。這個幀天然成爲了當前幀.在此方法執行期間,這個幀將用來保存參數,局部變量,中間計算過程和其餘數據.這個幀在這裏和編譯原理中的活動紀錄的概念是差很少的. 從Java的這種分配機制來看,堆棧又能夠這樣理解:堆棧(Stack)是操做系統在創建某個進程時或者線程(在支持多線程的操做系統中是線程)爲這個線程創建的存儲區域,該區域具備先進後出的特性。

每個Java應用都惟一對應一個JVM實例,每個實例惟一對應一個堆。應用程序在運行中所建立的全部類實例或數組都放在這個堆中,並由應用全部的線程 共享.跟C/C++不一樣,Java中分配堆內存是自動初始化的。Java中全部對象的存儲空間都是在堆中分配的,可是這個對象的引用倒是在堆棧中分配,也就是說在創建一個對象時從兩個地方都分配內存,在堆中分配的內存實際創建這個對象,而在堆棧中分配的內存只是一個指向這個堆對象的指針(引用)而已。
Java 把內存劃分紅兩種:一種是棧內存,另外一種是堆內存。在函數中定義的一些基本類型的變量和對象的引用變量都是在函數的棧內存中分配,當在一段代碼塊定義一個變量時,Java 就在棧中爲這個變量分配內存空間,當超過變量的做用域後,Java 會自動釋放掉爲該變量分配的內存空間,該內存空間能夠當即被另做它用。

圖片描述

(圖:JVM運行時數據區域分析)

上海尚學堂java培訓整理編輯,歡迎如下推薦內容或獲取學習資料與技術支持:

《【上海java培訓】Java內存區域、分配機制和GC垃圾回收算法》
《【上海Java培訓】Java虛擬機類初始化和類加載器》
《【上海Java培訓】Java基本數據類型和存放位置》

相關文章
相關標籤/搜索