GC
garbage collector
jdk8-gc
jdk默认的垃圾回收器查看..默认的其实有时候是最好的.
# 设置jvm参数Heap最大值 -XX:MaxHeapSize=
# 查看java默认的分配的大小,通过参数-XX:+PrintFlagsFinal 或者 -XX:+PrintCommandLineFlags 查找
> java [-XX:+PrintCommandLineFlags|-XX:+PrintFlagsFinal] -version
# 1. jdk8
## >java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=502370240
-XX:MaxHeapSize=8037923840
-XX:+PrintCommandLineFlags
-XX:+UseCompressedClassPointers
-XX:+UseCompressedOops
-XX:+UseParallelGC
### YG,OG使用不同组合的算法
### 一般业务场景使用的CMS,需要单打独配置,应为CMS部署JDk自带的GC回收器
# 2. jdk9
## >
-XX:G1ConcRefinementThreads=4
-XX:GCDrainStackTargetSize=64
-XX:InitialHeapSize=134217728
-XX:MaxHeapSize=2147483648
-XX:+PrintCommandLineFlags
-XX:ReservedCodeCacheSize=251658240
-XX:+SegmentedCodeCache
-XX:+UseCompressedClassPointers
-XX:+UseCompressedOops
-XX:+UseG1GC
####### YG,OG都使用G1算法
jdk部分源码
hotpot虚拟机源码,Heap大小(MaxHeapSize=byte)其实是2M的整数倍,用于查看heap的最大值,
# hotpot源码
size_t CollectorPolicy::compute_heap_alignment() {
// The card marking array and the offset arrays for old generations are
// committed in os pages as well. Make sure they are entirely full (to
// avoid partial page problems), e.g. if 512 bytes heap corresponds to 1
// byte entry and the os page size is 4096, the maximum heap size should
// be 512*4096 = 2MB aligned.
// (heap的512byte对应操作系统的一个byte,则系统的
// 一个page对应一个2M,即Heap大小与2M对齐,是2M的倍数,heap大小=2M*X)
// There is only the GenRemSet in Hotspot and only the GenRemSet::CardTable
// is supported.
// Requirements of any new remembered set implementations must be added here.
size_t alignment = GenRemSet::max_alignment_constraint(GenRemSet::CardTable);
// Parallel GC does its own alignment of the generations to avoid requiring a
// large page (256M on some platforms) for the permanent generation. The
// other collectors should also be updated to do their own alignment and then
// this use of lcm() should be removed.
if (UseLargePages && !UseParallelGC) {
// in presence of large pages we have to make sure that our
// alignment is large page aware
alignment = lcm(os::large_page_size(), alignment);
}
return alignment;
}
- -XX:InitialHeapSize=查看支持的初始堆大小,单位都是byte
- -XX:MaxHeapSize=查看jdk支持的最大堆大小,更系统内存有直接关系
UseParallelGC
JDK8默认垃圾回收器
UseParallelGC = Parallel Scavenge(YG) + PS MarkSweep(OG)
可见...jdk8环境下默认的gc工具是YG使用 Parallel Scavenge(支持高的吞吐),OG使用的Serial Old(其实应该是..PS MarkSweep算法..这是官方的错误...);
YG选择的逻辑可能是为了提高吞吐; 但是OG使用的并发线程,而且可能存在内存碎片.
PS MarkSweep应该是并行标记清除的,内存碎片
算法选择
- YG:提高吞吐计算,使用Parallel-Scanvenge,并发复制算法,是用空间换时间
- OG:使用PS MarkSweep,节省STW,并发清楚
Parallel-Scanvenge
Paralell Scanvenge(吞吐量优先的回收器)...适用于新生代,采用标记复制算法、多线程模型进行垃圾收集...
回收器选择考虑因素:吞吐量/STW时间
- 吞吐量 = 用户程序运行时间/(用户程序运行时间+GC时间); 主要是CPU密集型的场景。后台/cpu计算多的场景。
- STW时间,使用于用户交互多的场景 =>GC时间
主要的参数
-XX:MaxGCPauseMills:最大GC停顿时间(mills),注意不是越小越好,可能频繁YGC -XX:GCTimeRatio:GC时间/总时间比,默认=99,即1/(1+99)默认占1/100...GC的ratio概念都奇怪的... -XX:UseAdaptiveSizePolicy: 使用自适应的参数,不懂用这个就可以了...
PSMarkSweep
Serial old 单线程...标记整理算法..一般作为CMS的备选方案,在Concurrent Mode Failure情况下使用.
PS MarkSweep是以seril Old算法为模版设计.(有些官方使用serial old 代替了PSMarkSweep, JVM虚拟机就是)
补充: Concurrent Mode Failure(并发模式)失败是会发生FullGC...
CMS是适用于OG的GC算法..
- CMS触发FGC的可能
- CMS内存碎片
- CMS的YGC算法吞吐计算不如ps
CMS
CMS: YG使用ParNew, OG使用CMS,是支持出并发的
- 选择这个能减少STW
jdk9-gc
G1
对比CMS....重要的事情说三遍..。毕竟有人喜欢问为什么
- 通过预估模型,
可控停顿时间=> STW - 不会产生
内存碎片
G1毕竟是设计来替代CMS的,两者都是支持并发,大部分gc阶段是不会挂起用户线程的;不同的主要是上面2点.
设想对于使用大堆(MaxheapSize)的场景,又要求较小的系统STW时间(其实就是现在大型web应用的场景)..G1是目前最好的算法....
大神的图就是nb...再谢...
G1将整个堆heap分成多个region; 基于region和预估模型做增量回收...(预估回收region占用的时间不超过配置的时间)
G1有额外的空间占用,2个set集合Remembered Set(有引用的集合)和Collection Sets(需要被回收的集合)。 => 有点像GO的内存模型
- 整个堆大约认为2000个region,每个
region大小一致2M-32M(2M的倍数是不变的...) - 不同区(YG/OG/MP)的region大小可能不一样的
G1的优势
-
region的引入;主要解决GC碎片化的问题;同时实现JVM(YG/OG)逻辑上是连续空间而不需要物理是连续空间的问题
-
STW时间优化,通过参数配置STW期望时间,并通过预估模型增量回收region
-
-XX:G1HeapRegionSize=n设置region大小,1-32M -
g1最好使用自适应的配置
-
-XX:GCTimeRatio即为GC与应用的耗费时间比,G1默认为9,而CMS默认为99
jdk11-gc
jdk11引入
ZGC
- Pause times do not exceed 10ms
- Pause times do not increase with the heap or live-set size
- Handle heaps ranging from a few hundred megabytes to multi terabytes in size
-
STW延迟时间<10ms
-
STW不增加heap/live-set大小
-
heap大小支持MB-TB级别
-
标记、复制、迁移,所有操作并发
-
只有1代,不分YG、OG
-
系统内存需要支持numa-aware
pointer coloring
load barriers.
ps
- Oracle 官方出品,本文的很多内容是翻译并解读这篇文章的; Getting Started with the G1 Garbage Collector
- 帮助大家理解 G1 的日志; Understanding G1 GC Logs
- G1
- javadoop.com/post/g1