JDK1.8 JVM運行時數據區域划分以及 堆空間內存分配(默認情況下)


 

一、JDK1.8 JVM運行時數據區域概覽

 

 

 

這里介紹的是JDK1.8 JVM運行時內存數據區域划分。1.8同1.7比,最大的差別就是:元數據區取代了永久代。元空間的本質和永久代類似,都是對JVM規范中方法區的實現。不過元空間與永久代之間最大的區別在於:元數據空間並不在虛擬機中,而是使用本地內存。

 

 

 

二、各區域介紹

1. 程序計數器

每個線程一塊,指向當前線程正在執行的字節碼代碼的行號。如果當前線程執行的是native方法,則其值為null。

2. Java虛擬機棧

stack

線程私有,每個線程對應一個Java虛擬機棧,其生命周期與線程同進同退。每個Java方法在被調用的時候都會創建一個棧幀,並入棧。一旦完成調用,則出棧。所有的的棧幀都出棧后,線程也就完成了使命。

3. 本地方法棧
功能與Java虛擬機棧十分相同。區別在於,本地方法棧為虛擬機使用到的native方法服務。不多說。

4. 堆

 

 

 

 

 

 

 

堆是JVM內存占用最大,管理最復雜的一個區域。其唯一的用途就是存放對象實例:幾乎所有的對象實例及數組都在對上進行分配。1.7后,字符串常量池從永久代中剝離出來,存放在堆中。堆有自己進一步的內存分塊划分,按照GC分代收集角度的划分請參見上圖。

4.1 堆空間內存分配(默認情況下)

老年代 : 三分之二的堆空間
年輕代 : 三分之一的堆空間
eden區: 8/10 的年輕代空間
survivor0 : 1/10 的年輕代空間
survivor1 : 1/10 的年輕代空間(from 區)
命令行上執行如下命令,查看所有默認的jvm參數

java -XX:+PrintFlagsFinal -version

 

輸出:

 

 

 

 

 

 

4.2 字符串常量池

JDK1.7 就開始“去永久代”的工作了。 1.7把字符串常量池從永久代中剝離出來,存放在堆空間中。

a. jvm參數配置
-XX:MaxPermSize=10m
-XX:PermSize=10m
-Xms100m
-Xmx100m
-XX:-UseGCOverheadLimit

  

b. 測試代碼
public class StringOomMock {
	
	public static void main(String[] args) {
		try {
			List<String> list = new ArrayList<String>();
			for (int i = 0; ; i++) {
				System.out.println(i);
				list.add(String.valueOf("String" + i++).intern());
			}
		} catch (java.lang.Exception e) {
			e.printStackTrace();
		}
	}
}

  

 

 

 

5. 元數據區

元數據區取代了1.7版本及以前的永久代。元數據區和永久代本質上都是方法區的實現。方法區存放虛擬機加載的類信息,靜態變量,常量等數據。
元數據區OOM測試:

a. jvm參數配置

-XX:MetaspaceSize=8m 
-XX:MaxMetaspaceSize=50m

  

b. 測試代碼 

借助cglib框架生成新類。

 

public class MetaSpaceOomMock {
	
	public static void main(String[] args) {
		ClassLoadingMXBean loadingBean = ManagementFactory.getClassLoadingMXBean();
		while (true) {
			Enhancer enhancer = new Enhancer();
			enhancer.setSuperclass(MetaSpaceOomMock.class);
			enhancer.setCallbackTypes(new Class[]{Dispatcher.class, MethodInterceptor.class});
			enhancer.setCallbackFilter(new CallbackFilter() {
				@Override
				public int accept(Method method) {
					return 1;
				}
				
				@Override
				public boolean equals(Object obj) {
					return super.equals(obj);
				}
			});
			
			Class clazz = enhancer.createClass();
			System.out.println(clazz.getName());
			//顯示數量信息(共加載過的類型數目,當前還有效的類型數目,已經被卸載的類型數目)
			System.out.println("total: " + loadingBean.getTotalLoadedClassCount());
			System.out.println("active: " + loadingBean.getLoadedClassCount());
			System.out.println("unloaded: " + loadingBean.getUnloadedClassCount());
		}
	}
}

 

 

 

 

如果是1.7的jdk,那么報OOM的將是PermGen區域。

6. 直接內存

jdk1.4引入了NIO,它可以使用Native函數庫直接分配堆外內存。

 https://blog.csdn.net/bruce128/article/details/79357870

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM