在C/C++開發中,自己需要進行記憶體管理,而java由於JVM的自動記憶體管理機制的協助,不在需要為每一個new操作寫配對的delete和free代碼了,但由於記憶體泄露和益出方面的問題,在這小結下java記憶體地區中的一些知識。
java虛擬機器運行時資料區如下:
主要包括五個部分:程式計數器、java虛擬機器棧、本地方法棧、java堆、方法區(運行時常量池)。
(1)程式計數器(線程私人):
程式計數器是一塊較小的記憶體空間,它的作用可以看做事當前線程所執行的位元組碼的行號指標。如執行位元組碼指令、分支、迴圈、跳轉、異常處理、線程恢複等基礎功能。
JVM一次能支援很多線程執行。每一個JVM線程有它自己的程式計數器。在任何時候,一個JVM的線程都正在執行當前線程的方法代碼。如果這個方法是一個java方法,程式計數器記錄的是正在執行的虛擬機器位元組碼指令的地址。如果線程正在執行本地方法,程式計數器的值為未定義。JVM程式計數器足以儲存一個返回地址或一個本地指標。
(2)java虛擬機器棧(線程私人):
每個JVM的線程在建立的時候,都會建立一個棧。一個棧包含很多棧楨。棧幀用來儲存局部變數表(存放了編譯器的各種基礎資料型別 (Elementary Data Type)如boolean、byte、char、short、int、float、long、double;對象引用(不同虛擬機器儲存的不同如指向對象起始地址的引用指標或者是代表對象的控制代碼);returnaddress類型)、操作棧、動態連結、方法出口等資訊。
在java虛擬機器規範中,對這個地區規定了兩種異常狀況:
a。如果線程請求的棧深度大於虛擬機器所允許的深度,將拋出StackOverflowError異常。
b.如果VM棧可以動態擴充,當擴充時無法申請到足夠記憶體(或者在初始化新線程時沒有足夠記憶體在建立棧)則拋出OutOfMemoryError異常。
(3) 本地方法棧:
本地方法棧和java虛擬機器棧的作用類似。只是java虛擬機器棧為執行java方法(也就是位元組碼)服務,本地方法棧則為虛擬機器使用到的native方法服務。
在java虛擬機器規範中,對這個地區規定了兩種異常狀況:
a。如果線程請求的棧深度大於虛擬機器所允許的深度,將拋出StackOverflowError異常。
b.如果VM棧可以動態擴充,當擴充時無法申請到足夠記憶體(或者在初始化新線程時沒有足夠記憶體在建立棧)則拋出OutOfMemoryError異常。
(4)java堆
JVM有一個在所有線程內共用的堆。堆是給所有類的執行個體和數組分配記憶體的運行時資料區。 堆在虛擬機器啟動的時候建立,堆中儲存的對象通過一個自動儲存管理系統(記憶體回收行程)進行回收。 對象從不明確的被分配(JVM從不指明對象的釋放)。JVM加上沒有(JVM不指定特定的自動儲存管理系統)自動儲存管理系統的特別的類型,(開發人員可根據系統要求自主選擇)並且這個儲存管理技術可能被選擇按照實現的系統需求。
java堆是垃圾收集器管理的主要區域,也被稱為“GC堆”。
堆要麼是固定大小,要麼按計算需要擴充。如果一個大的堆變得多餘或許會收縮。堆的記憶體不需要相鄰。使用者可以設定堆記憶體的大小,如果堆能夠動態擴充。控制最大最小堆記憶體。
堆會出現以下異常:
如果記憶體溢出(若計算所需堆記憶體不足),則拋出OutOfMemoryError
(5)方法區
JVM的方法區是所有線程共用的,方法區類似於傳統語言編譯代碼時的儲存地區或類似於作業系統進程的文本段。他儲存內容包括:每一個類的結構,如運行時常量池,欄位和方法的資料;方法和構造器的代碼,如用於類,執行個體和介面初始化的特殊方法。這個方法區在JVM啟動的時候被建立,一般情況下JVM不會選擇對方法區進行記憶體回收或者壓縮,這個版本的JVM規範沒有強制規定方法區的位置和管理編譯後代碼的策略。方法區可固定大小,或按需伸縮。方法區的記憶體不需要相鄰。
運行時常量池(方法區的一部分):
運行時常量池是類和介面運行時的常量池表,它在位元組碼檔案裡。它包含幾類常量。 在編譯時間期識別的數值常量,在運行區識別的方法或引用欄位。運行區常量池類似於傳統語言的字元表,但它比傳統字元表所儲存的範圍更廣。每一個運行區常量池從方法區分配記憶體。當類和介面被JVM建立時相應的常量池也被建立。
運行區常量池包括以下異常:
當類和介面建立時,如果運行區常量池所需記憶體不足,則拋出OutOfMemoryError。