JVM GC机制收集器与GC调优.docx

上传人:b****8 文档编号:9533322 上传时间:2023-02-05 格式:DOCX 页数:20 大小:87.45KB
下载 相关 举报
JVM GC机制收集器与GC调优.docx_第1页
第1页 / 共20页
JVM GC机制收集器与GC调优.docx_第2页
第2页 / 共20页
JVM GC机制收集器与GC调优.docx_第3页
第3页 / 共20页
JVM GC机制收集器与GC调优.docx_第4页
第4页 / 共20页
JVM GC机制收集器与GC调优.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

JVM GC机制收集器与GC调优.docx

《JVM GC机制收集器与GC调优.docx》由会员分享,可在线阅读,更多相关《JVM GC机制收集器与GC调优.docx(20页珍藏版)》请在冰豆网上搜索。

JVM GC机制收集器与GC调优.docx

JVMGC机制收集器与GC调优

JVMGC机制、收集器与GC调优

一、回顾JVM内存分配

1.1、内存分配:

1、对象优先在EDEN分配

2、大对象直接进入老年代 

3、长期存活的对象将进入老年代 

4、适龄对象也可能进入老年代:

动态对象年龄判断

动态对象年龄判断:

虚拟机并不总是要求对象的年龄必须达到MaxTenuringThreshold才能晋升到老年代,当Survivor空间的相同年龄的所有对象大小总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无需等到MaxTenuringThreshold中指定的年龄

1.2、总结一下:

1、对象优先在Eden分配,这里大部分对象具有朝生夕灭的特征,MinorGC主要清理该处

2、大对象(占内存大)、老对象(使用频繁)

3、Survivor无法容纳的对象,将进入老年代,FullGC的主要清理该处

二、JVM的GC机制

JVM有2个GC线程

第一个线程负责回收Heap的Young区

第二个线程在Heap不足时,遍历Heap,将Young区升级为Older区

Older区的大小等于-Xmx减去-Xmn,不能将-Xms的值设的过大,因为第二个线程被迫运行会降低JVM的性能。

2.1、堆内存GC

JVM(采用分代回收的策略),用较高的频率对年轻的对象(younggeneration)进行YGC,而对老对象(tenured generation)较少(tenured generation满了后才进行)进行FullGC。

这样就不需要每次GC都将内存中所有对象都检查一遍。

2.2、非堆内存不GC

GC不会在主程序运行期对PermGenSpace进行清理,所以如果你的应用中有很多CLASS(特别是动态生成类,当然permgenspace存放的内容不仅限于类)的话,就很可能出现PermGenSpace错误。

2.3、内存申请、对象衰老过程

2.3.1、内存申请过程

1.JVM会试图为相关Java对象在Eden中初始化一块内存区域;

2.当Eden空间足够时,内存申请结束。

否则到下一步;

3.JVM试图释放在Eden中所有不活跃的对象(minorcollection),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区;

4.Survivor区被用来作为Eden及old的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区;

5.当old区空间不够时,JVM会在old区进行majorcollection;

6.完全垃圾收集后,若Survivor及old区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现"Outofmemory错误";

2.3.2、对象衰老过程

1.新创建的对象的内存都分配自eden。

Minorcollection的过程就是将eden和在用survivorspace中的活对象copy到空闲survivorspace中。

对象在younggeneration里经历了一定次数(可以通过参数配置)的minorcollection后,就会被移到oldgeneration中,称为tenuring。

GC触发条件

GC类型

触发条件

触发时发生了什么

注意

查看方式

YGC

eden空间不足

清空Eden+fromsurvivor中所有noref的对象占用的内存

将eden+fromsur中所有存活的对象copy到tosur中

一些对象将晋升到old中:

   tosur放不下的

   存活次数超过turningthreshold中的

重新计算tenuringthreshold(serialparallelGC会触发此项)

重新调整Eden和from的大小(parallelGC会触发此项)

全过程暂停应用

是否为多线程处理由具体的GC决定

jstat–gcutil 

gclog

FGC

old空间不足

perm空间不足

显示调用System.GC,RMI等的定时触发

YGC时的悲观策略

dumplive的内存信息时(jmap–dump:

live)

清空heap中noref的对象

permgen中已经被卸载的classloader中加载的class信息

如配置了CollectGenOFirst,则先触发YGC(针对serialGC)

如配置了ScavengeBeforeFullGC,则先触发YGC(针对serialGC)

全过程暂停应用

是否为多线程处理由具体的GC决定

是否压缩需要看配置的具体GC

jstat–gcutil 

gclog

permanentgeneration空间不足会引发FullGC,仍然不够会引发PermGenSpace错误。

三、GC监视、收集器与GC调优

3.1、监视JVMGC

首先说一下如何监视JVMGC,可以用JDK中的jstat工具,也可以在java程序启动的opt里加上如下几个参数(注:

这两个参数只针对SUN的HotSpotVM):

1.-XX:

-PrintGCPrintmessagesatgarbagecollection.Manageable.    

2.-XX:

-PrintGCDetailsPrintmoredetailsatgarbagecollection.Manageable.(Introducedin1.4.0.)    

3.-XX:

-PrintGCTimeStampsPrinttimestampsatgarbagecollection.Manageable(Introducedin1.4.0.)   

当把-XX:

-PrintGCDetails加入到javaopt里以后可以看见如下输出:

[GC[DefNew:

34538K->2311K(36352K),0.0232439secs]45898K->15874K(520320K),0.0233874secs]

[FullGC[Tenured:

13563K->15402K(483968K),0.2368177secs]21163K->15402K(520320K),[Perm:

28671K->28635K(28672K)],0.2371537secs]

他们分别显示了JVMGC的过程,清理出了多少空间。

第一行GC使用的是‘普通GC’(MinorCollections),第二行使用的是‘全GC’(MajorCollections)。

他们的区别很大,在第一行最后我们可以看见他的时间是0.0233874秒,而第二行的FullGC的时间是0.2371537秒。

第二行的时间是第一行的接近10倍,也就是我们这次调优的重点,减少FullGC的次数,以为FullGC会暂停程序比较长的时间,如果FullGC的次数比较多。

程序就会经常性的假死。

注:

GC信息的格式

[GC[:

->,secs]->,secs]

GC为minor收集过程中使用的垃圾收集器起的内部名称.

younggeneration在进行垃圾收集前被对象使用的存储空间.

younggeneration在进行垃圾收集后被对象使用的存储空间

minor收集使应用暂停的时间长短(秒) 

整个堆(HeapSize)在进行垃圾收集前被对象使用的存储空间

整个堆(HeapSize)在进行垃圾收集后被对象使用的存储空间

整个垃圾收集使应用暂停的时间长短(秒),包括major收集使应用暂停的时间(如果发生了major收集).

GC信息的选项

-XX:

+PrintGCDetails显示GC的详细信息

-XX:

+PrintGCApplicationConcurrentTime打印应用执行的时间

-XX:

+PrintGCApplicationStoppedTime打印应用被暂停的时间

3.2、collector收集器的种类

GC在HotSpotVM5.0里有四种:

incremental(sometimescalledtrain)lowpausecollector已被废弃,不在介绍.

类别

serialcollector

parallelcollector

( throughputcollector )

concurrentcollector

(concurrentlowpausecollector)

介绍

单线程收集器

使用单线程去完成所有的gc工作,没有线程间的通信,这种方式会相对高效

并行收集器

使用多线程的方式,利用多CUP来提高GC的效率

主要以到达一定的吞吐量为目标

并发收集器

使用多线程的方式,利用多CUP来提高GC的效率

并发完成大部分工作,使得gcpause短

试用场景

单处理器机器且没有pausetime的要求

适用于科学技术和后台处理

有中规模/大规模数据集大小的应用且运行在多处理器上,关注吞吐量(throughput)

适合中规模/大规模数据集大小的应用,应用服务器,电信领域

关注responsetime,而不是throughput

使用

Client模式下默认

可使用

可用-XX:

+UseSerialGC强制使用

优点:

对server应用没什么优点

缺点:

慢,不能充分发挥硬件资源

Server模式下默认

--YGC:

PSFGC:

ParallelMSC

可用-XX:

+UseParallelGC或-XX:

+UseParallelOldGC强制指定

--ParallelGC代表FGC为ParallelMSC

--ParallelOldGC代表FGC为ParallelCompacting

优点:

高效

缺点:

当heap变大后,造成的暂停时间会变得比较长

可用-XX:

+UseConcMarkSweepGC强制指定

优点:

对old进行回收时,对应用造成的暂停时间非常端,适合对latency要求比较高的应用

缺点:

1.内存碎片和浮动垃圾

2.old去的内存分配效率低

3.回收的整个耗时比较长

4.和应用争抢CPU

内存回收触发

YGC

eden空间不足

FGC

old空间不足

perm空间不足

显示调用System.gc(),包括RMI等的定时触发

YGC时的悲观策略

dumplive的内存信息时(jmap–dump:

live)

YGC

eden空间不足

FGC

old空间不足

perm空间不足

显示调用System.gc(),包括RMI等的定时触发

YGC时的悲观策略--YGC前&YGC后

dumplive的内存信息时(jmap–dump:

live)

YGC

eden空间不足

CMSGC

1.oldGen的使用率大的一定的比率默认为92%

2.配置了CMSClassUnloadingEnabled,且PermGen的使用达到一定的比率默认为92%

3.Hotspot自己根据估计决定是否要触法

4.在配置了ExplictGCInvokesConcurrent的情况下显示调用了System.gc.

FullGC(SerialMSC)

promotionfailed或concurrentModeFailure时;

内存回收触发时发生了什么

YGC

eden空间不足

FGC

old空间不足

perm空间不足

显示调用System.gc(),包括RMI等的定时触发

YGC时的悲观策略

dumplive的内存信息时(jmap–dump:

live)

YGC

同serial动作基本相同,不同点:

1.多线程处理

2.YGC的最后不仅重新计算TenuringThreshold,还会重新调整Eden和From的大小

FGC

1.如配置了ScavengeBeforeFullGC(默认),则先触发YGC(?

?

2.MSC:

清空heap中的noref对象,permgen中已经被卸载的classloader中加载的class信息,并进行压缩

3.Compacting:

清空heap中部分noref的对象,permgen中已经被卸载的classloader中加载的class信息,并进行部分压缩

多线程做以上动作.

YGC

同serial动作基本相同,不同点:

1.多线程处理

CMSGC:

1.oldgen到达比率时只清除oldgen中noref的对象所占用的空间

2.permgen到达比率时只清除已被清除的classloader加载的class信息

FGC

同serial

细节参数

可用-XX:

+UseSerialGC强制使用

-XX:

SurvivorRatio=x,控制eden/s0/s1的大小

-XX:

MaxTenuringThreshold,用于控制对象在新生代存活的最大次数

-XX:

PretenureSizeThreshold=x,控制超过多大的字节的对象就在old分配.

-XX:

SurvivorRatio=x,控制eden/s0/s1的大小

-XX:

MaxTenuringThreshold,用于控制对象在新生代存活的最大次数

-XX:

UseAdaptiveSizePolicy去掉YGC后动态调整edenfrom已经tenuringthreshold的动作

-XX:

ParallelGCThreads设置并行的线程数

-XX:

CMSInitiatingOccupancyFraction设置oldgen使用到达多少比率时触发

-XX:

CMSInitiatingPermOccupancyFraction,设置PermGen使用到达多少比率时触发

-XX:

+UseCMSInitiatingOccupancyOnly禁止hostspot自行触发CMSGC

注:

∙throughputcollector与concurrentlowpausecollector的区别是throughputcollector只在youngarea使用使用多线程,而concurrentlowpausecollector则在tenuredgeneration也使用多线程。

∙根据官方文档,他们俩个需要在多CPU的情况下,才能发挥作用。

在一个CPU的情况下,会不如默认的serialcollector,因为线程管理需要耗费CPU资源。

而在两个CPU的情况下,也提高不大。

只是在更多CPU的情况下,才会有所提高。

当然concurrentlowpausecollector有一种模式可以在CPU较少的机器上,提供尽可能少的停顿的模式,见CMSGCIncrementalmode。

∙当要使用throughputcollector时,在javaopt里加上-XX:

+UseParallelGC,启动throughputcollector收集。

也可加上-XX:

ParallelGCThreads=来改变线程数。

还有两个参数-XX:

MaxGCPauseMillis=和-XX:

GCTimeRatio=,MaxGCPauseMillis=用来控制最大暂停时间,而-XX:

GCTimeRatio可以提高GC说占CPU的比,以最大话的减小heap。

附注SUN的官方说明:

 

1.Thethroughputcollector:

thiscollectorusesaparallelversionoftheyounggenerationcollector.Itisusedifthe-XX:

+UseParallelGCoptionispassedonthecommandline.Thetenuredgenerationcollectoristhesameastheserialcollector.

2.Theconcurrentlowpausecollector:

thiscollectorisusedifthe-Xincgc™or-XX:

+UseConcMarkSweepGCispassedonthecommandline.Theconcurrentcollectorisusedtocollectthetenuredgenerationanddoesmostofthecollectionconcurrentlywiththeexecutionoftheapplication.Theapplicationispausedforshortperiodsduringthecollection.Aparallelversionoftheyounggenerationcopyingcollectorisusedwiththeconcurrentcollector.Theconcurrentlowpausecollectorisusediftheoption-XX:

+UseConcMarkSweepGCispassedonthecommandline.

3.Theincremental(sometimescalledtrain)lowpausecollector:

thiscollectorisusedonlyif-XX:

+UseTrainGCispassedonthecommandline.ThiscollectorhasnotchangedsincetheJ2SEPlatformversion1.4.2andiscurrentlynotunderactivedevelopment.Itwillnotbesupportedinfuturereleases.Pleaseseethe1.4.2GCTuningDocumentforinformationonthiscollector.

CMSGCIncrementalmode

当要使用concurrentlowpausecollector时,在java的opt里加上-XX:

+UseConcMarkSweepGC。

concurrentlowpausecollector还有一种为CPU少的机器准备的模式,叫Incrementalmode。

这种模式使用一个CPU来在程序运行的过程中GC,只用很少的时间暂停程序,检查对象存活。

在Incrementalmode里,每个收集过程中,会暂停两次,第二次略长。

第一次用来,简单从root查询存活对象。

第二次用来,详细检查存活对象。

整个过程如下:

*stopallapplicationthreads;dotheinitialmark;resumeallapplicationthreads(第一次暂停,初始话标记)

*dotheconcurrentmark(usesoneprocesorfortheconcurrentwork)(运行是标记)

*dotheconcurrentpre-clean(usesoneprocessorfortheconcurrentwork)(准备清理)

*stopallapplicationthreads;dotheremark;resumeallapplicationthreads(第二次暂停,标记,检查)

*dotheconcurrentsweep(usesoneprocessorfortheconcurrentwork)(运行过程中清理)

*dotheconcurrentreset(usesoneprocessorfortheconcurrentwork)(复原)

当要使用Incrementalmode时,需要使用以下几个变量:

-XX:

+CMSIncrementalModedefault:

disabled启动i-CMS模式(mustwith-XX:

+UseConcMarkSweepGC)

-XX:

+CMSIncrementalPacingdefault:

disabled提供自动校正功能

-XX:

CMSIncrementalDutyCycle=default:

50启动CMS的上线

-XX:

CMSIncrementalDutyCycleMin=default:

10启动CMS的下线

-XX:

CMSIncrementalSafetyFactor=default:

10用来计算循环次数

-XX:

CMSIncrementalOffset=default:

0最小循环次数(Thisisthepercentage(0-100)bywhichtheincrementalmodedutycycleisshiftedtotherightwithintheperiodbetweenminorcollections.)

-XX:

CMSExpAvgFactor=default:

25提供一个指导收集数

SUN推荐的使用参数是:

-XX:

+UseConcMarkSweepGC\

-XX:

+CMSIncrementalMode\

-XX:

+CMSIncrementalPacing\

-XX:

CMSIncrementalDutyCycleMin=0\

-XX:

CMSIncrementalDutyCycle=10\

-XX:

+PrintGCDetails\

-XX:

+PrintGCTimeStamps\

-XX:

-TraceClassUnloading

注:

如果使用throughputcollector和concurrentlowpausecollector,这两种垃圾收集器,需要适当的挺高内存大小,以为多线程做准备。

3.3、如何选择collector

∙app运行在单处理器机器上且没有pausetime的要求,让vm选择UseSerialGC.

∙重点考虑peakapplicationperformance(高性能),没有pausetime太严格要求,让vm选择或者UseParallelGC+UseParallelOldGC(optionally).

∙重

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 法语学习

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1