深入理解_JVM内存管理垃圾收集器05

1、垃圾收集器(内存回收方法的具体实现):

名词解释:

并行(Parallel):多条垃圾线程并行工作,但是此时用户线程仍然处于等待状态。

并发(Concurrent):指用户线程与垃圾收集线程同时执行(并不一定是并行的,可能会交替执行),用户程序继续运行,而垃圾收集程序运行于另一个CPU上。

HotSpot虚拟机包含的所有收集器如下图:

说明:

(a)JDK1.6_Update14之后引入了Early Access版G1收集器。

(b)如果两个收集器之间存在连线,就说明它们可以搭配使用。

<Young generation>:

(1)串行收集器(Serial):

(a)串行收集使用单线程,复制算法处理所有垃圾回收工作,因为无需多线程交互,实现容易,而且效率比较高。但是,其局限性也比较明显,即无法使用多处理器的优势,所以此收集适合单处理器机器。当然,此收集器也可以用在小数据量(100M左右)情况下的多处理器机器上。

(b)采用串行GC时,SurvivorRadio的值对应Eden Space/Survivor Space,SurvivorRadio默认的值为8。例如:当-Xmn为10MB时,Eden Space为8MB,2个Survivor Space各为1MB。

(c)目前仍然是Client模式下的新生代的默认收集方式。

(d)通常存活的对象在Minor GC之后,不会直接进入旧生代,而是需要经过几次Minor GC之后仍然活着,才会进入老生代。这个在Minor GC中存活的最大次数在串行和ParNew方式时可通过:

-XX:MaxTenuringThreshold来设置。

运行示意图如下:

缺点:进行回收时,必须暂停整个运行环境。

(2)ParNew收集器:

(a)并行收集就是Serial的多线程版本,也采用复制算法,使用多线程处理垃圾回收工作,因而速度快,效率高。而且理论上CPU数目越多,越能体现出并行收集器的优势。

(b)默认情况下它开启的收集线程数同CPU数量相同。在服务器CPU过多的情况下,可以使用:-XX:ParallelGCThreads参数来限制垃圾收集的线程数。

(c)ParNew也是通过SurvivorRatio值来划分空间,在开启UseAdaptiveSizePolicy后,则在每次Minor GC后动态计算Eden、to的大小。

(d)server模式下新生代默认使用该模式。

(e)与Parallel Scavenge区别:

<1>ParNew须配合老生代使用CMS GC,且ParNew GC不可与Parallel Old同时使用。

<2>在配置为使用CMS GC的情况下,新生代默认采用并行GC方式,也可通过:

-XX:+UseParNewGC来强制指定。

运行示意图如下:

缺点:进行回收时,需要暂停整个运行环境。

(3)Parallel Scavenge收集器(称为:吞吐量优先收集器):

<1> 该收集器也是一个新生代收集器,它也是使用复制算法的收集器。

<2> 默认情况下Eden、S0、S1的比例划分采用的为InitialSurvivorRatio,此值默认为8.可通过-XX:InitialSurvivorRatio进行调整。在Sun JDK1.6.0后也可通过-XX:SurvivorRatio来调整,但并行回收GC会将此值+2赋给InitialSurvivorRatio。当同时配置了:InitialSurvivorRatio和SurvivorRatio时,以InitialSurvivorRatio值为准。为保持和其他GC方式统一,建议配置SurvivorRatio。

<3> 当需要给对象分配内存时,Eden Space空间不够的情况下,如果此对象的大小>=Eden Space一半的大小,就直接在老生代上分配。

<4> Parallel Scavenge也是server级别,也可以通过-XX:UseParallelGC来强制指定,并行方式时默认的线程数根据CPU核数计算。当CPU核数<=8时,并行的线程数即为CPU核数;当CPU核数>8时,则为3+(CPU核数*5)/8,也可采用-XX:ParallelGCThreads来强制指定线程数。

<5> 与ParNew收集器的区别:

(a)关注点不同:

<1>Parallel Scavenge目标:达到一个可控制的吞吐量(Throughput)。吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,公式如下:

吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾回收时间)。

例如:虚拟机共运行100分钟,其中垃圾回收花掉2分钟,那吞吐量就是98%。

<2>其他收集器关注点:尽可能地缩短垃圾收集时用户线程的停顿时间。

(b)适合应用的场景:

<1>短停顿适合需要与用户交互的程序,提高用户体验。

<2>高吞吐量则可以最高效率地利用CPU时间,尽快完成程序的运算任务,适合在后台运算而不需要太多交互的任务。

<6> 参数设置:

(a)控制最大垃圾收集停顿时间的:-XX:MaxGCPauseMillis。允许值是一个大于0的毫秒数。

注意:将MaxGCPauseMillis参数设置小一点就能使垃圾收集速度变快,GC停顿时间缩短是以牺牲吞吐量和新生代空间来换取的:将新生代调小之后,每次收集速度肯定会提高,但是收集的频率反而会增加。

譬如:

10s执行一次,每次停顿100ms。1分钟=600ms。

5s执行一次,每次停顿70ms。1分钟=840ms。

(b)直接设置吞吐量大小的:-XX:GCTimeRatio。允许值是大于0而小于100的整数,也就是垃圾收集时间占总时间的比率,相当于吞吐量的倒数。

譬如:

设置参数为19。那么允许的最大GC时间就占总时间的5%(即:1/(1+19))。默认值为99,就是运行最大1%(即:1/(1+99))的垃圾收集时间。

(c) -XX:+UseAdaptiveSizePolicy参数开关,在运行一段时间后,会根据Minor GC的频率、消耗时间等来动态调整Eden、S0、S1的大小。可通过-XX:UseAdaptiveSizePolicy来固定Eden、S0、S1的大小。打开此开关就不需要手动指定新生代的大小(-Xmn)、Eden与Survivor区的比例等细节参数了。

<tenured generation>:

(4)Serial Old收集器:

是Serial收集器的老生代版本。单线程,Mark-Compact算法。

(5)Parallel Old收集器:

是Parallel Scavenge收集器的老年代版本。多线程,Mark-Compact算法。这个收集器在1.6之后才开始提供的。

在注重吞吐量及CPU资源敏感的场合,优先考虑Parallel Scavenge+Parallel Old组合。

(6)CMS(Concurrent Mark Sweep):

运行示意图如下:

是一种以获取最短回收停顿时间为目标的收集器。多线程,使用Mark Sweep算法。

整个过程包括4个步骤:

(a)初始标记(CMS initial mark):标记一下GC Roots能直接关联到的对象。

(b)并发标记(CMS concurrent mark):进行GC Roots Traing的过程。

(c)重新标记(CMS remark):修正并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录。消耗时间比初始标记长,但是短于并发标记时间。

(d)并发清除(CMS concurrent sweep)

初始标记和重新标记这2个步骤仍然需要暂停用户线程(Stop The World)。

最耗时的并发标记和并发清除阶段,收集器线程都可以与用户线程一起工作。

默认启动的回收线程数:

回收线程数:(CPU数量+3)/4。

当CPU数量大于4时,并发回收时垃圾收集器线程最多占用不超过25%的CPU资源,但当CPU数小于4时,CMS对用户程序的影响就可能变得很大,导致用户程序的执行速度忽然降低50%。为了解决此问题,虚拟机提供了一种“增量式并发收集器(i-CMS)”,就是让GC线程和用户线程交替运行,不过后续版本并不提倡用户使用此模式。这也是目前CMS的缺点之一,对CPU资源敏感。

运行示意图如下:

缺点:

(a)CMS收集器对CPU资源非常敏感。

(b)CMS运行过程中用户线程仍然在运行,会产生2个该模式下不可避免的问题:

(1)CMS收集器无法处理浮动垃圾,可能出现“Concurrent Mode Faile”失败而导致另一次Full GC的产生。由于CMS并发清除阶段用户线程仍然在运行,自然会产生新的垃圾,而这部分垃圾出现在标记过程之后,当次CMS无法处理掉他们,只要留在下一次GC时再将其清理掉,这就是“浮动垃圾”。

(2)CMS收集器无法像其他收集器那样等到老生代几乎被填满时再进行收集,必须预留一部分空间提供并发收集时的程序运行使用。默认设置下:CMS收集器在老生代使用了68%的空间后就会被激活,这是一个偏保守的设置,如果老生代增长较慢,可以使用-XX:CMSInitiatingOccupancyFraction的值来提高触发百分百比,以便降低回收次数获取更好的性能。如果CMS运行期间预留内存无法满足程序需要,就会出现一次“Concurrent Mode Faile”失败,此时虚拟机会启动后备方案,临时启用Serial Old收集器来重新进行老生代的垃圾收集,所以-XX:CMSInitiatingOccupancyFraction参数值不能设置太高。

(c)由于使用Mark-Sweep算法,所以会产生大量碎片。碎片过多将使大对象的分配很麻烦,而不得不提前进行Full GC。为了解决此问题,CMS收集器提供:-XX:+UseCMSCompactAtFullCollection开关参数。用于在完成Full GC之后,免费附送一个碎片整理过程,内存整理的过程是无法并发的。

(7) G1收集器:

是垃圾收集器最新的技术产物。优点如下:

(a)基于“标记-整理”算法,不会产生内存碎片。

(b)精确控制停顿。

G1对上述按代划分进行收集的方式更近一步,将整个JAVA堆(新生代,老生代)划分为多个大小固定的独立区域,并且跟踪这些区域里面的垃圾堆积程度,在后台维护一个优先列表,每次根据允许的收集时间,优先回收垃圾最多的区域(Garbage First)。

总结:

串行处理器:

--适用情况:数据量比较小(100M左右);单处理器下并且对响应时间无要求的应用。

--缺点:只能用于小型应用

并行处理器:

--适用情况:“对吞吐量有高要求”,多CPU、对应用响应时间无要求的中、大型应用。举例:后台处理、科学计算。

--缺点:垃圾收集过程中应用响应时间可能加长

并发处理器:

--适用情况:“对响应时间有高要求”,多CPU、对应用响应时间有较高要求的中、大型应用。举例:Web服务器/应用服务器、电信交换、集成开发环境。

时间: 2024-08-06 14:36:30

深入理解_JVM内存管理垃圾收集器05的相关文章

深入理解_JVM内存管理垃圾收集算法04

1.垃圾收集算法(方法论): 定义:JVM通过GC来回收堆和方法区中的内存. GC的基本原理:首先会找程序中不再被使用的对象:然后回收这些对象所占用的内存. 算法分类: (1) 按照基本回收策略分: <1>引用计数(Reference Counting): 比较古老的回收算法.原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数.垃圾回收时,只用收集计数为0的对象.此算法最致命的是无法处理循环引用的问题. <2> 标记-清除(Mark-Sweep): Before G

深入理解_JVM内存管理调优案例分析与实战10

1.高性能硬件上的程序部署策略 目前常用2种方式: (1)通过64位JDK来使用大内存: 使用第一种方式关键: <1>控制应用程序的Full GC频率.譬如10多个小时甚至一天才出现一次Full GC. 关键:大多数对象的生存时间不应该太长,保证老年代空间的稳定. 在大多数网站形势的应用里,主要对象的生存周期都是请求级或页面级的,会话级和全局级的长生命对象相对较少,控制住Full GC. 需要考虑的问题: <1>内存回收导致的长时间停顿: <2>现阶段,64位JDK的性

Java虚拟机的内存管理----垃圾收集器

1.Serial收集器 优点,是简单而高效,单线程避免了线程交互的开销. 缺点,进行垃圾回收时需要Stop the world(暂停所有用户线程). 2.ParNew收集器 它是Serial收集器的多线程版本,新生代才有多线程并行收集.是CMS收集器(下文会介绍)的默认新生代收集器. ParNew在单CPU的情况下,会比Serial收集器效率更差,因为多线程交互的开销. 但是,如今的计算机普遍是多CPU多核,而ParNew默认的线程数量是CPU的数量.因此它更加适应潮流. 3.Parallel

深入理解_JVM内存管理典型配置举例09

以下配置主要针对分代垃圾回收算法而言: 1.堆大小设置: 年轻代的设置很关键JVM中最大堆大小有三方面限制: (1)相关操作系统的数据模型(32-bt还是64-bit)限制: (2)系统的可用虚拟内存限制: (3)系统的可用物理内存限制.32位系统下,一般限制在1.5G~2G:64为操作系统对内存无限制.在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m. 典型设置: (1)场景一: java -Xmx3550m -Xms3550m -X

深入理解_JVM内存管理对象引用03

1.对象引用: (a)对象状态的判断: <1> 引用计数算法:无法解决对象相互引用的问题. <2> 根搜索算法:主流的判断对象是否存活的算法. (1)基本思路:通过一系列的名为:"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相关联时,证明此对象是不可用的,所以它们将会被判断为是可收回的对象. (2)Java中,GC Roots的对象包括下面几种:

深入理解_JVM内存管理内存分配和回收策略06

解决两个问题: 1.对象分配内存: 2.回收分配给对象的内存. 本节详细讲解分配的问题: 名词解释: 新生代GC(Minor GC):指发生在新生代的垃圾回收动作,非常频繁,回收速度很快. 老生代GC(Major GC/Full GC):指发生在老生代的垃圾回收动作,出现了Major GC,经常会伴随至少一次的Minor GC(但非绝对),速度一般会比Minor GC慢10倍. 打印日志说明: <1> DefNew:串行GC方式(Serial GC). <2> ParNew:Par

深入理解_JVM内存管理JDK监控工具与故障处理工具07

1.jps: JVM process Status Tool,显示系统所有的HotSpot虚拟机进程以及进程的本地虚拟机的唯一ID(LVMID,Local Virtual Machine Identifier). 对于本地虚拟机进程来说,LVMID与操作系统的进程ID(PID,Process Identifier)是一致的.如果启动了多个虚拟机进程,就需要显示主类的功能才能区分了. jps命令格式: jps [option] [hostid] jps主要选项: -v :输出虚拟机进程启动时JVM

深入理解_JVM内存管理JDK监控工具与故障处理工具08

Jconsole: Visial VM: 1.主要功能: (1)显示虚拟机进程及进程的配置和环境信息(jps,jinfo): (2)监视应用程序的CPU.GC.堆.方法区及线程信息(jstat,jstack): (3)dump及分析堆转储快照(jmap,jhat): (4)方法级的程序运行性能分析,找出被调用最多.运行时间最长的方法: (5)离线程序快照:收集程序的运行时配.线程dump.内存dump等信息建立一个快照,可以将快照发送开发者进行bug处理: (6)其他plus可能性. 2.生成和

垃圾收集器与内存分配策略之篇三:理解GC日志和垃圾收集器参数总结

一.GC日志片段如下: [GC[DefNew: 2658K->371K(4928K), 0.0038671 secs] 2658K->2419K(15872K), 0.0173438 secs] [Times: user=0.00 sys=0.00, real=0.02 secs] [Full GC[Tenured: 2048K->370K(10944K), 0.0331593 secs] 4564K->370K(15872K), [Perm : 176K->176K(122