首頁 > 軟體

Java的記憶體區域與記憶體溢位異常你瞭解嗎

2022-03-15 16:03:28

1. 執行時資料區域

1. 程式計數器(執行緒私有)

當前執行緒所執行的位元組碼的行號指示器,分支、迴圈、跳轉、例外處理、執行緒恢復等基礎功能都要考程式計數器。(記住程式當前走到的位置,下次還回來)。執行緒私有。

2. Java虛擬機器器棧(執行緒私有)

和方法相關聯,每個方法在執行的同時都會建立一個棧幀用於儲存區域性變數表、運算元棧、動態連結、方法出口等資訊。每一個方法從呼叫直至執行完成的過程,就對應著一個棧幀在虛擬機器器棧中入棧到出棧的過程

執行緒請求的棧深度大於虛擬機器器所允許的深度,將丟擲StackOverflowError異常(常見的遞迴層數過多導致”爆棧“)

3. 本地方法棧(執行緒私有)

類似於Java虛擬機器器棧。區別在於:

虛擬機器器棧為虛擬機器器執行Java方法本地方法棧則為虛擬機器器使用到的Native方法服務

Java開頭通過Java Native Interface來呼叫本地方法(一般用C語言編寫)

4. Java堆(執行緒共用)

Java虛擬機器器所管理的記憶體中最大的一塊new出來的物件就存在於堆上垃圾收集器管理的主要區域

5. 方法區(執行緒共用)

儲存已被虛擬機器器載入的類資訊、常數、靜態變數

6. 執行時常數池

方法區的一部分用於存放編譯期生成的各種字面量和符號參照

2. 物件是如何建立的?

Object obj=new Object(): 分析這行程式碼的執行過程

使用了new關鍵字,檢查這個指令的引數是否能在常數池中定位到一個類的符號參照,並且檢查這個符號參照代表的類是否已被載入、解析和初始化過。沒有的話先載入類類載入檢查通過後,虛擬機器器將為新生物件分配記憶體記憶體分配完成後,虛擬機器器需要將分配到的記憶體空間都初始化為零值虛擬機器器要對物件進行必要的設定,例如將物件的雜湊碼、後設資料、GC分代年齡、是否使用偏向鎖等資料存放在物件頭中執行init方法,把物件按照程式設計師的意願進行初始化(給成員變數賦的值)

3. 物件的記憶體佈局

4. 物件的存取定位

1. 控制程式碼存取

Java堆中將會劃分出一塊記憶體來作為控制程式碼池,reference中儲存的就是物件的控制程式碼地址,而控制程式碼中包含了物件範例資料與型別資料各自的具體地址資訊

2. 直接指標存取

Java堆物件的佈局中就必須考慮如何放置存取型別資料的相關資訊,而reference中儲存的直接就是物件地址

二者比較:

使用控制程式碼來存取的最大好處就是reference中儲存的是穩定的控制程式碼地址,即使物件被移動(GC過程),只需要改變控制程式碼中的範例指標,無需變動refrence直接指標存取方式的最大好處就是速度更快, refrence直接指向範例資料,減少了一次指標存取

HotSpot虛擬機器器使用直接指標方式進行物件存取的

5. OutOfMemoryError異常程式碼演示

1. Java堆溢位

package jvm;
import java.util.ArrayList;
import java.util.List;
public class OutOfMemoryErrorDemo {
	static class MyObject{
	}
	public static void main(String[] args) {
		List<MyObject> list=new ArrayList<>();
		int i=0;
		while(true)
		{
			System.out.println(i++);
			list.add(new MyObject());
		}
	}
}

限制Java堆的大小為20MB,不可延伸(將堆的最小值-Xms引數與最大值-Xmx引數設定為一樣即可避免堆自動擴充套件),通過引數-XX:+HeapDumpOnOutOfMemoryError可以讓虛擬機器器在出現記憶體溢位異常時Dump出當前的記憶體堆轉儲快照以便事後進行分析

2. 虛擬機器器棧溢位

如果執行緒請求的棧深度大於虛擬機器器所允許的最大深度,將丟擲StackOverflowError異常

package jvm;
import java.util.ArrayList;
import java.util.List;
public class OutOfMemoryErrorDemo {
	static int i=0;
	public static void main(String[] args) {
		f();
	}
	public static void f() {
		System.out.println(i++);
		f();
	}
}

相同的Xss(執行緒的堆疊大小)下,如果棧中的本地資料較多,那麼相應的可以遞迴的次數就越少

還有1種棧溢位會報OutOfMemoryError異常,如果虛擬機器器在擴充套件棧時無法申請到足夠的記憶體空間,則丟擲OutOfMemoryError異常,比如將上面的遞迴改成多執行緒版就會出現這種問題

總結

本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注it145.com的更多內容!  


IT145.com E-mail:sddin#qq.com