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中的堆疊和堆疊是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!