你的位置:首页 > Java教程

[Java教程][问题贴]小白请教几个关于Java虚拟机内存分配策略的问题


最近在看周志明所著的《深入理解Java虚拟机》,有几个问题不太明白,希望对虚拟机有研究的哥们儿帮我解答一下。
先说一下我进行试验的环境:

操作系统:Mac OS X 10.11.6 EI CapitanJava环境: java version "1.8.0_92"Java(TM) SE Runtime Environment (build 1.8.0_92-b14)Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

1. 我发现在年轻代中,即使我只是一个空类,没有进行任何的内存分配工作,Eden区域内存还是会被占用一部分,例子如下:

public class BlankedClassSize {  public static void main(String[] args) {  // TODO Auto-generated method stub  }}

虚拟机参数设置:

-verbose:gc -XX:+UseSerialGC -XX:+PrintGCDetails -Xmx20M -Xms20M -Xmn10M

虚拟机GC情况如下:

Heapdef new generation total 9216K, used1164K[0x00000007bf000000, 0x00000007bfa00000, 0x00000007bfa00000)eden space 8192K, 14% used [0x00000007bf000000, 0x00000007bf1231d0, 0x00000007bf800000)from space 1024K,  0% used [0x00000007bf800000, 0x00000007bf800000, 0x00000007bf900000)to  space 1024K,  0% used [0x00000007bf900000, 0x00000007bf900000, 0x00000007bfa00000)tenured generation  total 6144K, used 0K [0x00000007bfa00000, 0x00000007c0000000, 0x00000007c0000000)the space 6144K,  0% used [0x00000007bfa00000, 0x00000007bfa00000, 0x00000007bfa00200, 0x00000007c0000000)Metaspace    used 2666K, capacity 4486K, committed 4864K, reserved 1056768Kclass space  used 289K, capacity 386K, committed 512K, reserved 1048576K

问题1:这里是什么占用了内存?

2.当年轻代进行一次GC后,因为年轻代GC是采用复制算法收集内存的,那么正常情况下进行一次Minor GC后,Eden区域占存为什么不是零?是什么占用着内存?例子如下:

public class MinorGC {  private static final int_1MB = 1024*1024;    public static void main(String[] args) {    // TODO Auto-generated method stub    testEdenGC();  }  public static void testEdenGC(){    byte[] allocation1,allocation2,allocation3,allocation4,allocation5,allocation6;    allocation1=newbyte[_1MB];    allocation2=newbyte[_1MB];    allocation3=newbyte[_1MB];    allocation4=newbyte[_1MB];    allocation5=newbyte[_1MB];    allocation6=newbyte[_1MB];  }}

虚拟机参数设置:

-verbose:gc -XX:TenuringThreshold=1 -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRation=3 -XX:+PrintGCDetails -XX:+UseSerialGC

虚拟机GC情况:

[GC (Allocation Failure) DefNew: 6029K->1354K(8192K), 0.0032985 secs] 6029K->5450K(18432K), 0.0033216 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]Heapdef new generation  total 8192K, used 2440K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)eden space 6144K, 17% used [0x00000007bec00000, 0x00000007bed0f748, 0x00000007bf200000)from space 2048K, 66% used [0x00000007bf400000, 0x00000007bf5529b0, 0x00000007bf600000)to  space 2048K,  0% used [0x00000007bf200000, 0x00000007bf200000, 0x00000007bf400000)tenured generation  total 10240K, used 4096K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)the space 10240K, 40% used [0x00000007bf600000, 0x00000007bfa00040, 0x00000007bfa00200, 0x00000007c0000000)Metaspace    used 2666K, capacity 4486K, committed 4864K, reserved 1056768Kclass space  used 289K, capacity 386K, committed 512K, reserved 1048576K

问题2:根据6026K->1354K(8192K)可知,进行GC后,allocation1转入survivor1,allocation2~4转入老年区,此时eden中还有1354K内存被占用,是什么占用的?根据6029K->5450K(18432K),知道GC后,Java堆内存减少了579K,减少的这部分是谁的内存(明显新建的几个对象都可达,不至于被回收)?

3. 当给新对象分配内存的时候,因为年轻代空间不足,会发生一次minor GC,将年轻代中依然存活的对象复制到老年区,给新对象腾出空间,根据我的实验,此时若老年区内存不够将年轻代对象复制过去但是够新对象的存储,(此时会发生担保失败)则会直接将新对象放进老年代,例子如下:

public class MinorGC {  private static final int_1MB = 1024*1024;  public static void main(String[] args) {    // TODO Auto-generated method stub    testAllocation();  }  public static void testAllocation(){    byte[] allocation1,allocation2,allocation3,allocation4;    allocation1 = newbyte[2*_1MB];    allocation2 = newbyte[2*_1MB];    allocation3 = newbyte[2*_1MB];    allocation4 = newbyte[4*_1MB];  }}

 虚拟机参数设置如下:

-verbose:gc -Xms16M -Xmx16M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError -XX:MaxTenuringThreshold=15 -XX:+UseSerialGC

GC情况如下:

[GC (Allocation Failure) [DefNew (promotion failed) : 7144K->7474K(9216K), 0.0028055 secs][Tenured: 4096K->4096K(6144K), 0.0015627 secs] 7144K->6473K(15360K), [Metaspace: 2660K->2660K(1056768K)], 0.0044048 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]Heapdef new generation  total 9216K, used 6555K [0x00000007bf000000, 0x00000007bfa00000, 0x00000007bfa00000)eden space 8192K, 80% used [0x00000007bf000000, 0x00000007bf666ed0, 0x00000007bf800000)from space 1024K,  0% used [0x00000007bf900000, 0x00000007bf900000, 0x00000007bfa00000)to  space 1024K,  0% used [0x00000007bf800000, 0x00000007bf800000, 0x00000007bf900000)tenured generation  total 6144K, used 4096K[0x00000007bfa00000, 0x00000007c0000000, 0x00000007c0000000)the space 6144K, 66% used [0x00000007bfa00000, 0x00000007bfe00020, 0x00000007bfe00200, 0x00000007c0000000)Metaspace    used 2666K, capacity 4486K, committed 4864K, reserved 1056768Kclass space  used 289K, capacity 386K, committed 512K, reserved 1048576K

根据上面输出结果,可以看出,GC过程中,年轻代7144K->;7144K(9216K),并没有将年轻代中的对象转移走,而老年代中4096K->4096K(6144K),tenured generation   total 6144K, used 4096K,说明allocation4直接被转移到老年代中了。

问题3:难道这种情况下虚拟机会自动设置大对象阈值??将新对象直接放入老年去?

以上三个问题让我这个虚拟机小白百思不得其解,还希望大家帮我解释一下,在此谢过。




现在去泰国旅游多少钱泰国旅游几月份最好泰国旅游怎么样几月去泰国旅游最便宜怎样去泰国旅游广州梅花几月份最好看?广州梅花最佳观赏时间? 广州哪里有梅花节?广州冬天赏梅的好地方? 2015宁海县胡陈乡水蜜桃节什么时候开始举办?有什么活动? 广州梅花什么时间开放?广州梅花开花时间? 兴隆热带植物花园好玩吗?海南兴隆热带植物花园介绍? 大东海蜡像馆门票多少钱?三亚大东海蜡像馆团购价格? 三亚大东海蜡像馆好玩吗?大东海蜡像馆介绍? 三亚蜡像馆介绍?三亚趣味蜡像馆怎么样? 清远古龙峡漂流自驾游攻略?到古龙峡漂流在哪下高速? 清远怎么去古龙峡漂流?清远到古龙峡国际漂流基地乘车路线? 郑州马拉湾电话?马拉湾订票电话多少? 思罗河漂流电话?石表山思罗河漂流怎么预定? 2015年广东街坊文化节开幕式什么时候?广州街坊文化节举办地点在哪里? 华南植物园街坊欢乐节什么时候?广州华南植物园街坊欢乐节时间? 华南植物园中秋游园会活动时间?广州华南植物园中秋游园会有什么好玩的? 广州街坊文化节在哪里开幕?广东街坊文化节来华南植物园吗? SB1-10EWA Datasheet SB1-10EWA Datasheet SB1-10SRWA Datasheet SB1-10SRWA Datasheet SB1-7G3HWA Datasheet SB1-7G3HWA Datasheet 跑马山 跑马山 跑马山 鱼尾狮公园 鱼尾狮公园 鱼尾狮公园 小九寨 小九寨 小九寨