垃圾收集器的目的就是让应用程序开发者从人为进行动态内存管理中解放出来。开发者不需要分配和回收内存,不需要密切关注分配的动态内存的生命周期。Java HotSpot VM提供了一系列垃圾收集算法可供选择。
什么时候选择一个垃圾收集器很重要?
对于一些应用来说无所谓,也就是说在垃圾收集频率和暂停时间适中的情况下应用也可以运行的很好。然而,对于大型应用来说情况就不是这样的了,尤其是那些大数据量、多线程和很高TPS的系统。阿姆达尔定律说,并不是所用的任务都能很好的并行化,某些部分总是串行的。
在Java平台中,目前有四个支持的垃圾收集替代方案,除了其中一个serial GC之外,其他的都是并行工作,以提高性能。尽可能降低垃圾回收的开销是非常重要的
对于一些小的应用来说,串行收集器是很好的,而当应用部署在服务器类型的机器上时,默认情况下会选择Garbage-First (G1) collector。
On server-class machines, the following are selected by default:
• Garbage-First (G1) collector
• Initial heap size of 1/64 of physical memory
• Maximum heap size of 1/4 of physical memory
• Tiered compiler, using both C1 and C2
**基于行为的调优:Java HotSpot VM垃圾收集器可以配置为优先满足两个目标其中之一:最大暂停时间和应用程序吞吐量。
1.Maximum Pause-Time Goal
暂停时间是垃圾收集器停止应用程序的持续时间并回收不再使用的空间。这个目标的用意就是尽量缩短暂停时间。
可以通过命令行选项 -XX:MaxGCPauseMillis=<nnn>指定这个目标,指定了之后,垃圾收集器会调整堆大小和其他参数来尽量让暂停时间达到这个目标值。不过这些调整可能会导致GC的频率增加,从而会减少应用的整体吞吐量。
2.Throughput Goal
吞吐量目标是根据收集垃圾所花费的时间来衡量的,垃圾收集以外的时间就是应用程序的时间。这个目标是通过命令行选项-XX:GCTimeRatio=nnn指定的。垃圾收集时间与应用程序时间的比率为 1/ (1+nnn)。例如,-XX:GCTimeRatio=19表明1/20或者总时间的5%用于垃圾收集。花费在垃圾收集上的时间是所有垃圾收集引起暂停的总时间。如果吞吐量目标未被满足,那么垃圾收集器可能会增加堆的大小,这样在两次垃圾收集暂停之间的应用程序时间会更长,吞吐量相应的会提高。
**调优策略
1.不要为堆选择最大值除非你知道你需要一个大于默认最大堆大小的堆。为您的应用选择足够的吞吐量目标。
2.应用程序行为的更改可能会导致堆增大或缩小。例如,如果应用程序开始以更高的速率分配内存,则堆会增长保持相同的吞吐量。
3.如果堆增长到最大尺寸并且吞吐量目标未达到,那么最大堆空间对于设定的吞吐量目标来说太小。将最大堆大小设置为接近平台上总物理内存的值,但不会导致应用程序交换。如果吞吐量目标仍然没有达到,那么想要的应用程序时间目标对于平台上的可用内存来说太高。
4.如果吞吐量目标可以达到,但暂停时间太长,则设定一个最大暂停时间的目标。选择最大暂停时间目标可能意味着你的吞吐量目标将不会被满足,所以为应用程序选择可接受的折中值。
5.一般情况下,在垃圾收集器尽力满足这两个竞争目标时,堆的大小是不断波动的。在应用程序达到一个稳定状态时也会有这种情况。想达到吞吐量目标需要一个大堆,想达到maximum pause-time和minimum footprint(最小占用空间)都需要一个小堆。