《深入理解java虚拟机v3》大对象直接进入老年代 > 代码清单3-8

为什么要这样呢?

为了避免为大对象分配内存时的复制操作而降低效率。

详情

大对象就是指需要大量连续内存空间的Java对象,最典型的大对象便是那种很长的字符串,或者元素数量很庞大的数组,本节例子中的byte[]数组就是典型的大对象。

大对象对虚拟机的内存分配来说就是一个不折不扣的坏消息,比遇到一个大对象更加坏的消息就是遇到一群“朝生夕灭”的“短命大对象”,我们写程序的时候应注意避免。在Java虚拟机中要避免大对象的原因是,在分配空间时,它容易导致内存明明还有不少空间时就提前触发垃圾收集,以获取足够的连续空间才能安置好它们,而当复制对象时,大对象就意味着高额的内存复制开销。HotSpot虚拟机提供了-XX:PretenureSizeThreshold参数,指定大于该设置值的对象直接在老年代分配,这样做的目的就是避免在Eden区及两个Survivor区 之间来回复制,产生大量的内存复制操作

执行代码清单3-8中的testPretenureSizeThreshold()方法后,我们看到Eden空间几乎没有被使用,而老年代的10MB空间被使用了40%,也就是4MB的allocation对象直接就分配在老年代中,这是因为

-XX:PretenureSizeThreshold

被设置为3MB(就是3145728,这个参数不能与-Xmx之类的参数一样直接写3MB),因此超过3MB的对象都会直接在老年代进行分配。

注意 -XX:PretenureSizeThreshold参数只对Serial和ParNew两款新生代收集器有效,HotSpot的其他新生代收集器,如Parallel Scavenge并不支持这个参数。如果必须使用此参数进行调优,可考虑ParNew加CMS的收集器组合。

	private static final int _1MB = 1024 * 1024;

	/**
	 * VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails
	 * -XX:SurvivorRatio=8 -XX:+UseSerialGC -XX:+UseSerialGC
	 * -XX:PretenureSizeThreshold=3145728
	 */
	public static void testPretenureSizeThreshold() {
		byte[] allocation;
		allocation = new byte[4 * _1MB]; // 直接分配在老年代中
	}

	public static void main(String[] args) {
		testPretenureSizeThreshold();
	}

运行结果:

Heap
 def new generation   total 9216K, used 507K [0x32360000, 0x32d60000, 0x32d60000)
  eden space 8192K,   6% used [0x32360000, 0x323def28, 0x32b60000)
  from space 1024K,   0% used [0x32b60000, 0x32b60000, 0x32c60000)
  to   space 1024K,   0% used [0x32c60000, 0x32c60000, 0x32d60000)
 tenured generation   total 10240K, used 4096K [0x32d60000, 0x33760000, 0x33760000)
   the space 10240K,  40% used [0x32d60000, 0x33160010, 0x33160200, 0x33760000)
 compacting perm gen  total 12288K, used 380K [0x33760000, 0x34360000, 0x37760000)
   the space 12288K,   3% used [0x33760000, 0x337bf218, 0x337bf400, 0x34360000)
    ro space 10240K,  51% used [0x37760000, 0x37c925d0, 0x37c92600, 0x38160000)
    rw space 12288K,  55% used [0x38160000, 0x387fd978, 0x387fda00, 0x38d60000)

分析:
首先allocation申请4M内存,没有gc日志,说明没有触发GC;
新生代占用内存很小,老年代占用4M,说明allocation对象直接就分配在老年代中

Heap
 def new generation  新生代
  total 9216K,     
  used 507K     占用量很小
  [0x32360000, 0x32d60000, 0x32d60000)
  eden space 8192K,   6% used  eden区占用量很小 
  [0x32360000, 0x323def28, 0x32b60000)
  from space 1024K,   0% used [0x32b60000, 0x32b60000, 0x32c60000)
  to   space 1024K,   0% used [0x32c60000, 0x32c60000, 0x32d60000)
 tenured generation  老年代
  total 10240K, 
  used 4096K    占用4M,说明allocation存储到老年代了
  [0x32d60000, 0x33760000, 0x33760000)
   the space 10240K, 
    40% used       占用比例
   [0x32d60000, 0x33160010, 0x33160200, 0x33760000)
 compacting perm gen  total 12288K, used 380K [0x33760000, 0x34360000, 0x37760000)
   the space 12288K,   3% used [0x33760000, 0x337bf218, 0x337bf400, 0x34360000)
    ro space 10240K,  51% used [0x37760000, 0x37c925d0, 0x37c92600, 0x38160000)
    rw space 12288K,  55% used [0x38160000, 0x387fd978, 0x387fda00, 0x38d60000)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值