您好,登錄后才能下訂單哦!
這篇文章主要介紹“Java中的堆和棧是什么”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Java中的堆和棧是什么”文章能幫助大家解決問題。
Java程序運行在Java Virtual Machine (JVM)中,JVM提供了Java應用程序在運行時所需要的任何資源的管理器。這就意味著開發者寫的應用程序或者創建的應用程序沒有能力去直接獲取系統資源(不管是硬件還是軟件),除非JVM能提供給這些資源。所以在Java中,程序運行順序如下圖:
JVM層使得Java平臺能夠獨立運行,其他編程語言,例如C/C++沒有使用類似JVM層的東西,因此它們不是跨平臺的語言,即使它們是可移植的語言。它們就像下圖一樣:
這兩種形式有優點也有缺點,Java已經有了自己的生態系統。與此同時,像C/C++這樣的編程語言能夠直接訪問系統資源,從而更有利于優化核心單元的使用,從而產生超級快速和高效的程序。但兩者在軟件開發領域都有各自的用途。
所有編程語言在編譯和執行過程中都有許多相似之處。其中最重要的一點就是內存管理,無論使用哪種語言,內存管理對程序的整體效率都有重要影響,因為管理好內存資源,從而才能管理好應用程序性能。
應用程序之間的一個常見現象是,每個應用程序都需要一些內存才能以最佳方式工作,該內存由底層平臺提供。在Java中,JVM提供了這些內存資源(當然需要操作系統授權)。Java中,JVM內存主要分為5個部分分別為:方法區、堆、棧、PC寄存器和本地方法區。
本文主要關注堆和棧。內存不像一張白紙,程序員只需要草草記下就可以存儲數據,在使用內存之前,需要對其進行結構化。棧和堆是使用內存時遵循的數據結構,在程序執行期間,存儲的數據用于各種目的,這取決于程序的目的是什么。
JVM決定程序執行期間使用的運行時數據區域。有些數據區域是依賴于JVM的,這意味著它們是在JVM啟動時創建的,并在JVM的整個生命周期中持續存在。但是,每個線程都創建和銷毀其他數據區域。JVM可以同時執行多個執行線程,這意味著每個線程都有自己的pc(Program Counter,程序計數器)來維護正在執行的當前指令的位置,還有一個棧幀來保存靜態內存分配。
棧是內存中的一種結構,開發人員在其中存儲元素,其方式允許只從棧頂檢索數據——通常稱為先入后出(FILO或LIFO)。因為每個線程都維護一個私有的JVM棧,它被用來存儲與它們的靜態內存分配相關的變量。特定于我們在代碼中聲明和使用的方法的原語變量實際上存儲在棧區域中。另外,對實際存儲在堆內存中的對象的引用也存儲在堆棧區域中。因此,任何本地分配的內存都存儲在堆棧中。
堆棧內存的默認大小可以使用JVM參數-Xss來更改。有時,如果分配了太多變量或方法遞歸調用自身,則堆棧可能溢出。所有Java程序員都知道的一個常見錯誤是Java.lang.stackoverflowerror
,當棧內存不足時提示該錯誤。Java中的每個方法調用都會在棧中分配一塊內存,因此,設計糟糕的遞歸方法調用很容易占用所有棧內存,導致棧內存溢出錯誤。
堆是JVM一啟動就創建的內存區域,它會一直存在,直到JVM被銷毀。與棧不同的是,棧是單個線程的屬性(因為每個線程都有自己的棧),堆實際上是由JVM本身管理的全局內存,此內存在運行時用于為對象分配內存。因此,對象的實例化可以是用戶定義的類、JDK或其他庫類。簡而言之,使用new
關鍵字創建的任何對象都存儲在堆內存中。堆內存中的對象可被JVM運行的所有線程訪問。訪問管理非常復雜,使用了非常復雜的算法,這就是JVM垃圾收集器發揮作用的地方。
堆的默認大小可以使用JVM參數-Xms
和-Xmx
來更改。隨著對象的創建和銷毀,堆的大小也會增加或減少,如果達到最大內存限制后并嘗試進一步分配內存,則拋出java.lang.OutOfMemoryError
。
Java.lang.String
類是Java中使用最多的類,因此,應該特別注意它的效率問題。與基本數據類型相比,字符串的操作效率總是很慢,所以,必須采用某種方式使得字符串對象操作的效率和便利性方面類似或者接近于基本數據類型,為了達到這個目的就在堆中分配了一塊特殊內存區域(StringPool),創建的任何字符串對象都由JVM存儲在StringPool中。與堆中創建的其他對象相比,這提高了性能。
為了更好地說明在Java中堆和棧內存的使用,讓我們寫一個簡單的程序,并決定哪個分配分配到哪個內存——堆或棧:
public class HeapAndStackTest { public static void main(String[] args) { int x=10; int y=20; String greet = "Hello"; Date d = new Date(); diff(x, y); } public static int diff(int x1, int x2) { return x2-x1; } }
這段代碼運行方式如下:
程序啟動,JVM將Java運行時環境(JRE)類加載到堆中。
在遇到main()
方法時,會創建一個棧幀。
局部變量x
和y
存儲在棧中。
字符串greet
分配在堆的StringPool區域中。
Date
對象分配在堆區,而它的引用d
存儲在棧中。
關于“Java中的堆和棧是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。