垃圾收集器与内存分配策略(20)


-XX:参数允许的值是一个大于0的毫秒数,收集器将尽力保证内存回收花费的时间不超过用户设定值 。不过大家不要异想天开地认为如果把这个参数的值设置得更小一点就能使得系统的垃圾收集速度变得更快,垃圾收集停顿时间缩短是以牺牲吞吐量和新生代空间为代价换取的:系统把新生代调得小一些,收集300MB新生代肯定比收集500MB快,但这也直接导致垃圾收集发生得更频繁,原来10秒收集一次、每次停顿100毫秒,现在变成5秒收集一次、每次停顿70毫秒 。停顿时间的确在下降,但吞吐量也降下来了 。
-XX:参数的值则应当是一个大于0小于100的整数,也就是垃圾收集时间占总时间的比率,相当于吞吐量的倒数 。譬如把此参数设置为19,那允许的最大垃圾收集时间就占总时间的5%(即1/(1+19)),默认值为99,即允许最大1%(即1/(1+99))的垃圾收集时间 。
由于与吞吐量关系密切,收集器也经常被称作“吞吐量优先收集器” 。除上述两个参数之外,收集器还有一个参数-XX:+y值得我们关注 。这是一个开关参数,当这个参数被激活之后,就不需要人工指定新生代的大小(-Xmn)、Eden与区的比例(-XX:)、晋升老年代对象大小(-XX:ld)等细节参数了,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量 。这种调节方式称为垃圾收集的自适应的调节策略(GC ) 。如果读者对于收集器运作不太了解,手工优化存在困难的话,使用 收集器配合自适应调节策略,把内存管理的调优任务交给虚拟机去完成也许是一个很不错的选择 。只需要把基本的内存数据设置好(如-Xmx设置最大堆),然后使用-XX:参数(更关注最大停顿时间)或-XX:(更关注吞吐量)参数给虚拟机设立一个优化目标,那具体细节参数的调节工作就由虚拟机完成了 。自适应调节策略也是 收集器区别于收集器的一个重要特性 。
收集器提供了两个参数用于精确控制吞吐量,分别是控制最大垃圾收集停顿时间的-XX:参数以及直接设置吞吐量大小的-XX:参数 。
Old收集器
Old是收集器的老年代版本,它同样是一个单线程收集器,使用标记-整理算法 。这个收集器的主要意义也是供客户端模式下的虚拟机使用 。如果在服务端模式下,它也可能有两种用途:一种是在JDK 5以及之前的版本中与 收集器搭配使用,另外一种就是作为CMS收集器发生失败时的后备预案,在并发收集发生 Mode 时使用
Old收集器
Old是 收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实现 。这个收集器是直到JDK 6时才开始提供的,在此之前,新生代的 收集器一直处于相当尴尬的状态,原因是如果新生代选择了 收集器,老年代除了 Old(PS )收集器以外别无选择,其他表现良好的老年代收集器,如CMS无法与它配合工作 。由于老年代 Old收集器在服务端应用性能上的“拖累”,使用 收集器也未必能在整体上获得吞吐量最大化的效果 。同样,由于单线程的老年代收集中无法充分利用服务器多处理器的并行处理能力,在老年代内存空间很大而且硬件规格比较高级的运行环境中,这种组合的总吞吐量甚至不一定比加CMS的组合来得优秀 。
直到 Old收集器出现后,“吞吐量优先”收集器终于有了比较名副其实的搭配组合,在注重吞吐量或者处理器资源较为稀缺的场合,都可以优先考虑 加 Old收集器这个组合 。Old收集器的工作过程如图
CMS收集器
CMS( Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器 。目前很大一部分的Java应用集中在互联网网站或者基于浏览器的B/S系统的服务端上,这类应用通常都会较为关注服务的响应速度,希望系统停顿时间尽可能短,以给用户带来良好的交互体验 。CMS收集器就非常符合这类应用的需求 。