深入理解JVM的内存结构及GC机制
GC (Garbage Collector) 的四种类型:
- 串行回收器(SerialGC)是单线程的一个回收器,简单、易实现、效率高。
参数-XX:+UseSerialGC
就是Young区和old区都使用serial 垃圾回收算法, - 并行回收器(ParNewGC)是Serial的多线程版,可以充分的利用CPU资源,减少回收的时间。
参数-XX:+UseParallelGC
Young区:使用Parallel scavenge 回收算法
Old 区:可以使用单线程的或者Parallel 垃圾回收算法,由 -XX:+UseParallelOldGC 来控制 - 并发标记清除回收器(CMS,Concurrent Mark Sweep)是一种以获取最短回收停顿时间为目标的回收器,该回收器是基于“标记-清除”算法实现的。
参数-XX:+UseConcMarkSweepGC
Young区:可以使用普通的或者 parallel 垃圾回收算法,由参数 -XX:+UseParNewGC来控制
Old 区:只能使用Concurrent Mark Sweep - 垃圾优先回收器(G1, Garbage First),使用G1的目的是简化性能优化的复杂性。
G1 GC由Young Generation和Old Generation组成。G1将Java堆空间分割成了若干个Region,即年轻代/老年代是一系列Region的集合,这就意味着在分配空间时不需要一个连续的内存区间,即不需要在JVM启动时决定哪些Region属于老年代,哪些属于年轻代。因为随着时间推移,年轻代Region被回收后,又会变为可用状态了。
参数:-XX:+UseG1GC
CG常用参数(基于JAVA 8)
-XX:G1NewSizePercent
:初始年轻代占整个Java Heap的大小,默认值为5%;
-XX:G1MaxNewSizePercent
:最大年轻代占整个Java Heap的大小,默认值为60%;
-XX:G1HeapRegionSize
:设置每个Region的大小,单位MB,需要为1,2,4,8,16,32其一,默认是堆内存的1/2000。前面我们讲过大对象概念,如果这个值设置比较大,那么大对象就可以进入Region了,同样地,这样做的坏处是直接干预了各年龄代的分配大小;
-XX:ConcGCThreads
:与Java应用一起执行的GC线程数量。默认是Java线程的1/4。减少这个参数的数值可能会提升并行回收的效率,即提高系统内部吞吐量(系统是一个整体,CPU资源大家都需要占用),不过如果这个数值过低,也会导致并行回收机制耗时加长;
-XX:+InitiatingHeapOccupancyPercent
(简称IHOP):G1内部并行循环启动的设置值,默认为Java Heap的45%。这个可以理解为老年代空间占用的空间,GC收集后需要低于45%的占用率。这个值主要是为了决定在什么时间启动老年代的并行回收循环,这个循环从初始化并行回收开始,可以避免Full GC的发生;
-XX:G1HeapWastePercent
:G1不会回收的内存大小,默认是堆大小的5%。GC会收集所有的Region,如果值达到5%,就会停下来不再收集了; -XX:G1MixedGCCountTarget
:设置并行循环之后需要有多少个混合GC启动,默认值是8个。老年代Regions的回收时间通常比年轻代的收集时间要长一些,所以如果混合收集器比较多,可以允许G1延长老年代的收集时间;
-XX:+G1PrintRegionLivenessInfo
:这个参数需要和-XX:+UnlockDiagnosticVMOptions
配合启动,这可以理解,它们本身就是属于VM的调试信息。如果开启了,VM会打印堆内存里每个Region的存活对象信息。这个信息在标记循环结束后可以打印出来;
-XX:G1ReservePercent
:这个值是为了保留一些空间用于年代之间的提升,默认值是堆空间的10%。注意这个空间保留后就不会用在年轻代了,大家可以看到GC日志里输出显示,我们大量执行的是年轻代回收,所以如果你的应用里面有比较大的堆内存空间、比较多的大对象存活,那还是减少一点保留空间吧,这样会给年轻代更多的预留空间、GC之间更长的处理时间;
-XX:+G1SummarizeRSetStats
:这个也是一个VM的调试信息。如果启用,会在VM推出的时候打印出RSets的详细总结信息。如果启用-XX:G1SummaryRSetStatsPeriod
参数,就会阶段性地打印RSets信息;
-XX:+G1TraceConcRefinement
:这个也是一个VM的调试信息。如果启用,并行回收阶段的日志就会被详细打印出来;
-XX:+GCTimeRatio
:大家知道,GC的有些阶段是需要Stop-the-World,即停止应用线程的,这个参数就是计算花在Java应用线程上和花在GC线程上的时间比率,默认是9。这个参数主要的目的是让用户可以控制花在应用上的时间,G1的计算公式是100/(1+GCTimeRatio),这样如果采用9,则最多10%的时间会花在GC工作上面。Parallel GC的默认值是99,表示1%的时间被用在GC上面,这是因为Parallel GC贯穿整个GC,而G1则根据Region来进行划分,不需要全局性扫描Java Heap;
-XX:+UseStringDeduplication
:手动开启Java String对象的分割工作,这个是JDK8u20之后新增的参数,主要用于相同String避免重复申请内存,节约Region的使用;
-XX:MaxGCPauseMills
:G1停止执行的一个目标值,单位是毫秒,默认是200毫秒,这个值不一定真的会达到。这个参数会通过控制年轻代的大小来实现目标。
-XX:+PrintGCDateStamps
-XX:+PrintGCDetails
-Xloggc:../path_to/gc.log
-XX:InitiatingHeapOccupancyPercent
-XX:+ParallelRefProcEnabled
-XX:NewSize
-XX:MaxGCPauseMillis
-XX:MaxNewSize
-XX:InitialCodeCacheSize
-XX:ReservedCodeCacheSize
-XX:MetaspaceSize
-XX:MaxMetaspaceSize
参考:
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 using1174@foxmail.com
文章标题: 深入理解JVM的内存结构及GC机制
文章字数: 1,493
本文作者: Jun
发布时间: 2018-10-29, 12:26:00
最后更新: 2019-11-20, 21:38:07
原始链接: http://yoursite.com/2018/10/29/深入理解JVM的内存结构及GC机制/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。