再议JVM的垃圾回收

 

JDK 5.0这个版本中就存在四种垃圾回收器(Collector),一般我们不会去选择配置特定的回收器,就会使用默认的叫做Serial Collector。其他三种分别是Throughput CollectorConcurrentCollectorTrain Collector(最老的向前兼容版本)

 

大部分情况下是不需要关注特定的GC种类,除非这个应用需要在垃圾回收这方面展现出独到的特性。在JDK 1.3之前是不存在并行回收的,所以即时在多处理器的系统中垃圾回收并不会加快速度。直到后续推出了并行回收(ThroughputConcurrent两种才有),即在应用程序运行的同时跑回收线程。

 

为了优化性能,在JVM Heap中的内存是按照管理对象的年龄即年代(存活时间)来划分区间的,每个区间装满对象之后都会触发不同种类的GC。首先对象在初始化的时候会在Young区域分配空间,并且根据”infant mortality”原则,很多对象都会直接在Young区域被回收,而不会有机会与其他区扯上关系。当Young区被装满时会触发Minor回收,Minor回收针对的是首次被分配空间的部分存活对象,所以执行的速度非常快。回收之后存活下来的对象将会被转移到Tenured区。当Tenured区装满的时候会触发Full回收,而Full回收由于要检查所有Live Objects所以执行的速度就要慢得多。

 

 

JVM中各种GC管理的Heap空间默认结构如下——(Throughput Collector除外)

 

 

在初始化的时候有很大一部分物理内存是没有被分配到GC计算之内的,也就是我们看到的Young区和Tenured区的两个Virtual部分,只有当真正需要的时候才会讲这些空间也加入GC使用。途中的Young区由一个Eden区和两个很小的Survivor区组成,Objects初始化的时候都在Eden区,两个很小的Survivor(from区和to)to区总是为空,它要作为下一次GC操作时Edenfrom区中存活对象的缓冲区,缓冲到对象足够old然后这些存活对象就会被搬到象征着老年代的Tenured区。在Tenured右侧的叫Perm区,也就是持久代,它是用来存在Class信息和Methods信息的,不参与GC,同样它也有一个预设大小和一个可调整的Virtual块。

 

衡量JVMGC的性能主要有两个指标:ThroughputPausesThroughput是除去非GC时间所占总时间的比例,而Pauses指应用程序在GC发生时所产生的停滞时间。

 

这是Sun JVM的垃圾回收机制,值得关注的是Full GC会造成的停滞非常影响性能,应该尽量的避免,可是Sun JVM有个特点是当一次性要分配很大内存的对象时,往往会直接放到Tenured区,这样很容易就会触发Full GC。相对而言IBM的JVM就不分年轻代(Young)和年老代(Tenured),它对管理的内存直接按照Hash表结构来存储对象,等于划分成了一个个不同大小的格子,当触发GC时,就会把可以回收的格子清空,而下次分配对象就找到能装下的最近的一个格子。默认方式下,并不会去挪动剩下的对象来合并格子碎片,除非设置相映的参数去触发合并,但是又会牺牲扫描的时间。所以说JVM的垃圾回收并不是万能的,虽然不用写代码的人去操心,但某些情况下会出现无法避免的性能问题。

 

我们所能做的就是了解JVM GC机制和可以设置的参数,在特定应用和需求下采取最恰当的方式来做GC。



评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值