亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

《JVM筆記》之一:Java內存區域與內存溢出異常

系統 1797 0

Java與C++之間有一堵由內存動態分配和垃圾收集技術所圍成的高墻,墻外面的人想進去,墻里面的人卻想出來。

按照《Java虛擬機規范(第2版)》的規定,Java虛擬機所管理的內存將包括以下幾個運行時數據區域,來個圖更加直觀點,如下圖所示:


《JVM筆記》之一:Java內存區域與內存溢出異常
?

解釋下各個部分

?

程序計數器:

Program Counter Register是一塊較小的內存空間,它的作用可以看做是當前線程所執行的字節碼的行號指示器。 每個線程都有一個獨立的程序計數器,各個線程之間計數器互不影響,獨立存儲。此內存區域是唯一一個在Java虛擬機規范中沒有規定任何OutOfMemoryError情況的區域。

?

Java虛擬機棧:

也是線程私有的,它的生命周期與線程相同。每個方法被執行的時候會同時創建一個棧幀(Stack Frame)用于存儲局部變量表、操作棧、動態鏈接、方法出口等信息。每個方法被調用直至執行完成的過程,就對應著一個棧幀在虛擬機中從入棧到出棧的過程。

如果線程請求棧深度大于虛擬機所允許的深度,拋出StackOverflowError

如果虛擬機棧可以動態擴展,擴展時無法申請到足夠的內存時會拋出OutOfMemoryError

?

本地方法棧:

Native Method Stacks與虛擬機棧所發揮的作用是非常相似的,只不過一個是執行Java方法,一個是Nataive方法,HotSpot虛擬機直接將兩者合二為一了

?

Java堆:

Java堆是被所有線程共享的一塊內存區域,在虛擬機啟動時創建。Java堆是垃圾收集器管理的主要區域,很多時候稱為GC堆。

如果在堆中沒有內存完成實例分配,并且堆也無法再擴展時,將會拋出OutOfMemoryError

?

方法區:

Method Area與Java堆一樣,是各個線程共享的內存區域,它用于存儲已被虛擬機加載的類信息、常量、靜態變量、JIT編譯后的代碼等數據。

當方法區無法滿足內存分配需求時,將拋出OutOfMemoryError。

?

運行時常量池:

Runtime Constant Pool是方法區的一部分。用于存放編譯器生成的各種字面量和符號引用,這部分內容將在類加載后存放到方法區的運行時常量池中。

當常量池無法再申請到內存時會拋出OutOfMemoryError異常。

?

直接內存:

Direct Memory并不是虛擬機運行時數據區的一部分,也不是Java虛擬機規范中定義的內存區域,但是這部分也是頻繁使用。在Java的NIO中使用到,服務器管理員忽略直接內存后果是,各個內存區域總和大于物理內存限制,從而導致動態擴展時出現OutOfMemoryError異常。

?

?

?實戰:OutOfMemoryError異常:

1,Java堆溢出:

Java堆用于存儲對象實例,我們只要不斷創建對象,并且保證GC Roots到對象之間有可達路徑來避免GC清除這些對象,就會在對象數量到達最大堆的容量限制后產生內存溢出異常。

VM Args: -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError

XX:+HeapDumpOnOutOfMemoryError這個參數可以讓虛擬機在出現內存溢出異常時Dump出當前的內存堆轉儲快照以便事后進行分析。

?

      import java.util.ArrayList;
import java.util.List;

/**
 * VM Args: -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError
 * @author Administrator
 *
 */
public class HeapOOM {
	static class OOMObject{
		private String name;
		public OOMObject(String name) {
			this.name = name;
		}
	}
	public static void main(String[] args) {
		List<OOMObject> list = new ArrayList<OOMObject>();
		long i = 1;
		while(true) {
			list.add(new OOMObject("IpConfig..." + i++));
		}
	}
}
    
?拋出的異常:

?

Dumping heap to java_pid27828.hprof ...

Heap dump file created [14123367 bytes in 0.187 secs]

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

at java.lang.AbstractStringBuilder.<init>(AbstractStringBuilder.java:45)

at java.lang.StringBuilder.<init>(StringBuilder.java:92)

at com.baoxian.HeapOOM.main(HeapOOM.java:22)

?

?注:出現Java堆內存溢出時,異常堆棧信息?java.lang.OutOfMemoryError?后面會緊跟著?Java heap space。

要解決這個異常,一般手段是首先通過內存映像分析工具比如Eclipse Memory Analyzer對dump出來的堆轉儲快照進行分析,重點是確認內存中對象是否是必要的,也就是要弄清楚到底是出現了內存泄露 Memory Leak還是內存溢出 Memory Overflow。

如果是內存泄露,可進一步通過工具查看泄露對象到GC Roots的引用鏈。于是就能找到泄露對象時通過怎樣的路徑與GC Roots相關聯并導致垃圾收集器無法自動回收它們。掌握了泄露對象的類型信息,以及GC Roots引用鏈的信息,就可以比較準確的定位出泄露代碼的位置了。

如果不存在泄露,那么就該修改-Xms 和 -Xms堆參數看能否加大點。

?

2,虛擬機棧和本地方法棧溢出

-Xoss參數設置本地方法棧大小,對于HotSpot沒用。棧容量只由-Xss參數設定。

?

      /**
 * VM Args: -Xss128k
 * @author Administrator
 *
 */
public class JavaVMStackSOF {
	private int stackLength = 1;
	public void stackLeak() {
		stackLength++;
		stackLeak();
	}
	public static void main(String[] args) throws Throwable{
		JavaVMStackSOF oom = new JavaVMStackSOF();
		try {
			oom.stackLeak();
		} catch (Throwable e) {
			System.out.println("stack length: " + oom.stackLength);
			throw e;
		}

	}

}
    
?

?

?拋出異常:

stack length: 1007

Exception in thread "main" java.lang.StackOverflowError

at com.baoxian.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:11)

at com.baoxian.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12)

at com.baoxian.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12)

at com.baoxian.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12)。。。。

?

3,運行時常量池溢出:

運行時常量池分配在方法區內,可以通過 -XX:PermSize和 -XX:MaxPermSize限制方法區大小,從而間接限制其中常量池的容量。

?

      import java.util.ArrayList;
import java.util.List;

/**
 * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M
 * @author Administrator
 *
 */
public class RuntimeConstantPoolOOM {
	public static void main(String[] args) {
		// 使用List保持著常量池引用,避免Full GC回收常量池行為
		List<String> list = new ArrayList<String>();
		// 10MB的PermSize在integer范圍內足夠產生OOM了
		int i = 0;
		while (true) {
			list.add(String.valueOf(i++).intern());
		}
	}
}
    
?異常:

?

Exception in thread "main" java.lang.OutOfMemoryError: PermGen space

at java.lang.String.intern(Native Method)

at com.baoxian.RuntimeConstantPoolOOM.main(RuntimeConstantPoolOOM.java:18)

運行時常量池溢出,在java.lang.OutOfMemoryError后面緊跟著是PermGen space

?

4,方法區溢出:

方法區用于存放Class的相關信息,如類名、訪問修飾符、常量池、字段描述符、方法描述等。對于這個區域的測試,基本的思路是運行時產生大量的類去填滿方法區,直到溢出。比如動態代理會生成動態類。

使用CGLib技術直接操作字節碼運行,生成大量的動態類。當前很多主流框架如Spring和Hibernate對類進行增強都會使用CGLib這類字節碼技術,增強的類越多,就需要越大的方法區來保證動態生成的Class可以加載入內存。

異常:

Exception in thread "main" java.lang.OutOfMemoryError: PermGen space

at java.lang.String.intern(Native Method)

同樣,跟常量池一樣,都是PermGen space字符串出現

方法區溢出也是一種常見的內存溢出異常,一個類如果要被垃圾收集器回收,判定條件是非常苛刻的。在經常動態生成大量Class的應用中,需要特別注意類的回收狀況。這類場景除了上面提到的程序使用GCLib字節碼技術外,常見的還有: 大量JSP或動態產生的JSP文件的應用(JSP第一次運行時需要編譯為Java類)、基于OSGi應用等。

?

5,本機直接內存溢出:

DirectMemory容量可以通過-XX:MaxDirectMemorySize指定,如果不指定,則默認與Java堆的最大值-Xmx指定一樣。

      /**
 * VM Args: -Xmx20M -XX:MaxDirectMemorySize=10M
 * @author Administrator
 *
 */
public class DirectMemoryOOM {
	private static final int _1MB = 1024 * 1024;
	public static void main(String[] args) {
		Field unsafeField = Unsafe.class.getDeclaredFields()[0];
		unsafeField.setAccessible(true);
		Unsafe unsafe = (Unsafe) unsafeField.get(null);
		while(true) {
			unsafe.allocateMemory(_1MB);
		}
	}
}
    

?

在OutOfMemoryError后面不會有任何東西了,這就是DirectMemory內存溢出了。

?

本人博客已搬家,新地址為: http://yidao620c.github.io/

《JVM筆記》之一:Java內存區域與內存溢出異常


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 日韩精品区| 欧洲精品视频在线观看 | 久久这里只有精品66re99 | 成年看片永远免费 | 美女久草 | 美女被草视频 | 久久久噜噜噜久久老司机 | 国产三级做爰高清视频a | 99久久99久久久99精品齐 | 色91在线 | 色综合亚洲天天综合网站 | 91av综合| 久久的爱久久的你 | 黄色片一级毛片 | 成人性毛片 | 成人黄色一级视频 | 99热成人精品国产免男男 | 一级毛片短视频 | 中文字幕天天躁夜夜狠狠综合 | 欧美精品香蕉在线观看网 | 伊人久久青草青青综合 | 一区二区视频在线观看免费的 | 国产成人影院一区二区 | 国产亚洲精品热视频在线观看 | 亚洲欧美日韩国产vr在线观 | 九热视频在线观看 | 成人精品国产亚洲欧洲 | 一区二区三区四区视频在线 | 久久好看视频 | 欧美亚洲日本国产 | 欧美亚洲国产一级毛片 | 久久综合香蕉久久久久久久 | a在线观看免费视频 | 色综合亚洲七七久久桃花影院 | 全亚洲最大的免费私人影剧院 | 在线看国产精品 | 久久精品一区 | 毛片免费观看视频 | 欧美成人一区二区三区 | 香蕉毛片 | 久久久久国产精品免费 |