网站如何与域名绑定,wordpress本地打开慢,适合个人做的外贸平台,手机单页网站生成系统相关概念
并行和并发
并行#xff08;Parallel#xff09; 指多条垃圾收集线程并行工作#xff0c;但此时用户线程仍然处于等待状态。
并发#xff08;Concurrent#xff09; 指用户线程与垃圾收集线程同时执行#xff08;但不一定是并行的#xff0c;可能会交替执行…相关概念
并行和并发
并行Parallel 指多条垃圾收集线程并行工作但此时用户线程仍然处于等待状态。
并发Concurrent 指用户线程与垃圾收集线程同时执行但不一定是并行的可能会交替执行用户程序在继续运行。而垃圾收集程序运行在另一个CPU上。
Minor GC 和 Full GC
新生代GCMinor GC 指发生在新生代的垃圾收集动作因为Java对象大多都具备朝生夕灭的特性所以Minor GC非常频繁一般回收速度也比较快。
老年代GCMajor GC / Full GC 指发生在老年代的GC出现了Major GC经常会伴随至少一次的Minor GC但非绝对的在Parallel Scavenge收集器的收集策略里就有直接进行Major GC的策略选择过程。Major GC的速度一般会比Minor GC慢10倍以上。
吞吐量Throughput
吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值即
吞吐量 运行用户代码时间 /运行用户代码时间 垃圾收集时间。
假设虚拟机总共运行了100分钟其中垃圾收集花掉1分钟那吞吐量就是99%。
GC Root
GC Root 包含以下对象
虚拟机栈栈帧中的本地变量表中引用的对象本地方法栈中 JNI即一般说的 Native 方法引用的对象方法区中类静态属性引用的对象方法区中常量引用的对象
Serial/Serial Old 收集器
这是两款最基本的垃圾回收器一般用于客户端模式下适合单核或者配置较低的情况。曾经JDK 1.3.1之前是虚拟机新生代收集的唯一选择。
Serial
新生代垃圾收集器标记复制算法单个垃圾收集线程会产生Stop The World。
# 添加该参数来显式的使用Serial垃圾收集器。
-XX:UseSerialGCSerial Old
老年代垃圾收集器标记-整理算法单个垃圾收集线程Stop The World可作为CMS收集器并发失败时的后备预案。
Par New / Parallel Old 收集器
相比于Serial/Serial Old这两款垃圾收集器也很类似主要区别是引入了多个垃圾收集线程但收集的时候仍然是需要Stop The World的无法与用户线程并发。
Par New
新生代垃圾收集器标记复制算法多个垃圾收集线程Stop The World经常与CMS垃圾收集器搭配使用。
# 指定使用CMS后会默认使用ParNew作为新生代收集器。
-XX:UseConcMarkSweepGC
# 强制指定使用ParNew。
-XX:UseParNewGC
# 指定垃圾收集的线程数量ParNew默认开启的收集线程与CPU的数量相同。
-XX:ParallelGCThreadsParallel Old
老年代垃圾收集器标记整理算法多个垃圾收集线程Stop The World,与Paralle Scavenge收集器搭配使用。
Parallel Scavenge收集器
新生代垃圾收集器与Parallel Old搭配使用与Par New 类似采用多个垃圾收集线程会产生Stop The World但是相对于Par New它有着一些独特的特点优势。
首先它是一款以吞吐量优先的垃圾收集器可以通过-XXGGTimeRatio来达到设置吞吐量的目的。
另一个特点是它有一个自适应调节策略可通过-XX:UseAdaptiveSizePolicy这个开关参数开启自适应调节开启后它将自动调节新生代大小Eden与Survivor的比例晋升老年代对象大小等参数值从而尽量满足设置的吞吐量参数或者停顿时间参数。
# Parallel Scavenge收集器提供了两个参数来用于精确控制吞吐量
#一是控制最大垃圾收集停顿时间的 -XXMaxGCPauseMillis参数
#二是控制吞吐量大小的 -XXGCTimeRatio参数#参数允许的值是一个大于0的毫秒数收集器将尽可能的保证内存垃圾回收花费的时间不超过设定的值但是并不是越小越好GC停顿时间缩短是以牺牲吞吐量和新生代空间来换取的如果设置的值太小将会导致频繁GC这样虽然GC停顿时间下来了但是吞吐量也下来了。
-XXMaxGCPauseMillis# 参数的值是一个大于0且小于100的整数也就是垃圾收集时间占总时间的比率默认值是99就是允许最大1%即1/199的垃圾收集时间。
-XXGCTimeRatio#参数是一个开关如果这个参数打开之后虚拟机会根据当前系统运行情况收集监控信息动态调整新生代的比例、老年大大小等细节参数以提供最合适的停顿时间或最大的吞吐量这种调节方式称为GC自适应的调节策略。
-XXUseAdaptiveSizePolicyCMSConcurrent Mark Sweep收集器
老年代垃圾收集器与Par New搭配使用。
它是一款以最小回收停顿时间优先的垃圾收集器也是Hotspot第一款真正采用并发收集算法的垃圾收集器。采用了标记-清除算法在标记阶段利用增量更新解决并发标记问题。
其缺点也很明显会产生大量的内存碎片且吞吐量也不高。在进行Full GC时会对内存碎片利用整理算法进行整理会Stop The World。并发清除阶段可能用户线程会没有足够的内存空间分配对象导致分配失败此时会以Serial Old收集器作为分配失败的后备预案会Stop The World。 CMS收集器工作的整个流程分为以下4个步骤
初始标记CMS initial mark仅仅只是标记一下GC Roots能直接关联到的对象速度很快需要“Stop The World”。并发标记CMS concurrent mark进行GC Roots Tracing的过程在整个过程中耗时最长。重新标记CMS remark为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录这个阶段的停顿时间一般会比初始标记阶段稍长一些但远比并发标记的时间短。此阶段也需要“Stop The World”。并发清除CMS concurrent sweep
由于整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作。
优点
CMS是一款优秀的收集器它的主要优点在名字上已经体现出来了并发收集、低停顿因此CMS收集器也被称为并发低停顿收集器Concurrent Low Pause Collector。
缺点
对CPU资源非常敏感 其实面向并发设计的程序都对CPU资源比较敏感。在并发阶段它虽然不会导致用户线程停顿但会因为占用了一部分线程或者说CPU资源而导致应用程序变慢总吞吐量会降低。CMS默认启动的回收线程数是CPU数量3/4也就是当CPU在4个以上时并发回收时垃圾收集线程不少于25%的CPU资源并且随着CPU数量的增加而下降。但是当CPU不足4个时比如2个CMS对用户程序的影响就可能变得很大如果本来CPU负载就比较大还要分出一半的运算能力去执行收集器线程就可能导致用户程序的执行速度忽然降低了50%其实也让人无法接受。无法处理浮动垃圾Floating Garbage 可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。由于CMS并发清理阶段用户线程还在运行着伴随程序运行自然就还会有新的垃圾不断产生。这一部分垃圾出现在标记过程之后CMS无法再当次收集中处理掉它们只好留待下一次GC时再清理掉。这一部分垃圾就被称为“浮动垃圾”。也是由于在垃圾收集阶段用户线程还需要运行那也就还需要预留有足够的内存空间给用户线程使用因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集需要预留一部分空间提供并发收集时的程序运作使用。标记-清除算法导致的空间碎片 CMS是一款基于“标记-清除”算法实现的收集器这意味着收集结束时会有大量空间碎片产生。空间碎片过多时将会给大对象分配带来很大麻烦往往出现老年代空间剩余但无法找到足够大连续空间来分配当前对象。
JVM参数配置
## 新生代 ParNew 老年代 CMS 老年代 Serial Old
# 某些版本的参数是这样的 -XX:UseConcurrentMarkSweepGC
-XX:UseConcMarkSweepGC# 响应时间优先停顿时间是一个建议时间GC会尝试用各种手段达到这个时间比如减小年轻代默认 18446744073709551615
-XX:MaxGCPauseMillis
# 吞吐量优先设置JVM吞吐量要达到的目标值 GC时间占用程序运行时间的百分比的差值默认是 99
# 也就应用程序线程应该运行至少99%的总执行时间GC占 1%
-XX:GCTimeRatio99# 并行收集器ParNew , STW, YGC的线程数默认CPU所支持的线程数如果CPU所支持的线程数大于8则 默认 8 (logical_processor -8)*(5/8)
-XX:ParallelGCThreads
# CMS垃圾回收线程数量
-XX:ParallelCMSThreads# 解决 CMS Memory Fragmentation 碎片化 开启FGC时进行压缩以及多少次FGC之后进行压缩
-XX:UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction3
# 解决 CMS Concurrent mode failure Promotion Failed晋升失败
# 使用多少比例的老年代后开始CMS收集默认是68%(近似值)如果频繁发生SerialOld卡顿应该调小频繁CMS回收
-XX:UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction70# 开启 CMS 元空间的垃圾回收
-XX:CMSClassUnloadingEnabled
# -XX:CMSInitiatingPermOccupancyFraction JDK8已经移除G1Garbage First收集器
以CMS收集器替代者的身份出现同样以最小回收停顿时间为目标是JDK9的默认垃圾收集器JDK8是Parallel Scanvenge Parallel Old组合。
它开创了以局部收集思想和面向Region的内存布局以Region做为最小回收单元多个Region组成回收机CSet。同样这款垃圾收集器中也包含着分代收集思想不过不同于之间的收集器将堆内存划分为新生代老年代的布局。
G1将堆空间按固定大小1M-32M可通过启动参数设定划分为多个Region每个Region都可以根据需要作为新生代Eden,Survivor老年代(Old)或者说大对象Humongous大小超过Region一半当做老年代对待。
G1的特点是建立了停顿时间模型在M毫秒的时间片内 消耗在垃圾收集上的时间不超过N毫通过启动参数XX:MaxGCPauseMillis可指定最大停顿时间。
实现原理在垃圾收集过程中记录每个Region回收耗时等信息计算出平均值标准偏差置信度等统计信息从而预测出由哪些Region组成的回收集才可以在不超过设置的停顿时间约束下获得最高的收益。 G1的收集过程如上图所示。其主保证并发标记正确性的解决方案是原始快照SATB区别于CMS的增量更新在筛选回收阶段更新Region统计数据根据回收价值排序选择回收集回收。 所以从整体上看G1还是基于标记-整理算法的只实现了标记阶段的与用户线程并发回收阶段还是要Stop The World。这种方式导致其没有内存碎片问题。但如果能实现其整理阶段的并发速度就更快了其实整理阶段的并发实现还是比价难得在后来的Shenandoah和ZGC收集器便实现了整理阶段的并发。
G1具备如下特点
并行与并发 G1 能充分利用多CPU、多核环境下的硬件优势使用多个CPU来缩短“Stop The World”停顿时间部分其他收集器原本需要停顿Java线程执行的GC动作G1收集器仍然可以通过并发的方式让Java程序继续执行。分代收集 与其他收集器一样分代概念在G1中依然得以保留。虽然G1可以不需要其他收集器配合就能独立管理整个GC堆但它能够采用不同方式去处理新创建的对象和已存活一段时间、熬过多次GC的旧对象来获取更好的收集效果。空间整合 G1从整体来看是基于“标记-整理”算法实现的收集器从局部两个Region之间上来看是基于“复制”算法实现的。这意味着G1运行期间不会产生内存空间碎片收集后能提供规整的可用内存。此特性有利于程序长时间运行分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。可预测的停顿 这是G1相对CMS的一大优势降低停顿时间是G1和CMS共同的关注点但G1除了降低停顿外还能建立可预测的停顿时间模型能让使用者明确指定在一个长度为M毫秒的时间片段内消耗在GC上的时间不得超过N毫秒这几乎已经是实时JavaRTSJ的垃圾收集器的特征了。
G1收集器运行流程
G1收集器的运作大致可划分为以下几个步骤
初始标记Initial Marking 仅仅只是标记一下GC Roots 能直接关联到的对象并且修改TAMSNest Top Mark Start的值让下一阶段用户程序并发运行时能在正确可以的Region中创建对象此阶段需要停顿线程但耗时很短。并发标记Concurrent Marking 从GC Root 开始对堆中对象进行可达性分析找到存活对象此阶段耗时较长但可与用户程序并发执行。最终标记Final Marking 为了修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录虚拟机将这段时间对象变化记录在线程的Remembered Set Logs里面最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set中这阶段需要停顿线程但是可并行执行。筛选回收Live Data Counting and Evacuation 首先对各个Region中的回收价值和成本进行排序根据用户所期望的GC 停顿是时间来制定回收计划。此阶段其实也可以做到与用户程序一起并发执行但是因为只回收一部分Region时间是用户可控制的而且停顿用户线程将大幅度提高收集效率。
JVM参数配置
# JDK 9开始为默认垃圾回收器
-XX:UseG1GC# 响应时间优先建议值设置最大GC停顿时间(GC pause time)指标(target). 这是一个软性指标(soft goal)
# JVM 会尽力去达成这个目标. 所以有时候这个目标并不能达成
# G1会尝试调整Young区的块数来达到这个值
-XX:MaxGCPauseMillis
# 响应时间优先GC的停顿间隔时间默认0
-XX:GCPauseIntervalMillis
# 吞吐量优先设置JVM吞吐量要达到的目标值 GC时间占用程序运行时间的百分比的差值默认是 99
# 也就应用程序线程应该运行至少99%的总执行时间GC占 1%
-XX:GCTimeRatio99# 并发回收器STW YGC的工作线程数量默认CPU所支持的线程数如果CPU所支持的线程数大于8则 默认 8 (logical_processor -8)*(5/8)
-XX:ParallelGCThreads
# G1 并发标记线程数量
-XX:ConcGCThreads# 启动并发GC时的堆内存占用百分比. G1用它来触发并发GC周期,基于整个堆的使用率,而不只是某一代内存的使用比例。默认45%
# 当堆存活对象占用堆的45%就会启动G1 中Mixed GC
-XX:InitiatingHeapOccupancyPercent
# G1 分区大小建议逐渐增大该值1 2 4 8 16 32。
# 随着size增加垃圾的存活时间更长GC间隔更长但每次GC的时间也会更长。ZGC做了改进动态区块大小
-XX:G1HeapRegionSize# 新生代最小比例默认为5%
# -XX:G1NewSizePercent JDK8u23已经移除 https://www.oracle.com/technical-resources/articles/java/g1gc.html
# 新生代最大比例默认为60%
# -XX:G1MaxNewSizePercent JDK823已经移除 https://www.oracle.com/technical-resources/articles/java/g1gc.html
# G1 新生代初始大小默认为5%
-XX:NewSize
# G1 新生代最大大小
-XX:MaxNewSizeShenandoah收集器
这是一款低延迟垃圾收集器其目标是在尽可能对吞吐量影响不大的前提下实现在任何堆内存大小下都可以把垃圾收集时间限制在10ms以内。它是OpenJDK12正式特性之一和G1收集器有很多相似之处甚至公用了一部分源代码。
相比之下它有许多的改进点。比如实现了并发的整理算法用连接矩阵替代了G1的记忆集。要实现并发整理却有一个非常大的难点与用户线程并发的情况下移动对象用户线程可能在收集线程移动过程中对被移动的对象进行读写访问。Shenandoah采取的解决方案是读屏障转发指针
读屏障可以理解为虚拟机层面对对象访问操作的AOP切面说白了就是在访问对象之前要干点什么事转发指针在原有对象布局结构的最前面统一加一个引用字段在不处于并发移动的情况下该引用指向对象自己。当对象有了一份新的副本时只需修改该引用值指向新的副本虚拟机对旧对向的访问就会转发到新对象上去。
ZGC收集器
它也是一款低延迟收集器目标同Shenandoah一样从目前的表现来看比Shenandoah更强大是JDK11发布的一款垃圾收集器。它的特点是Region具有动态性—动态创建和销毁动态的区域容量大小。此外它同样实现了并发的整理算法。其实现方案是染色指针多重映射
染色指针将少量额外的信息直接存储在指针上在64位操作系统中Linux系统只支持46位的物理地址空间64TB染色指针将这46位中的4位拿出来存储4个标志信息如对象的三色标记状态、是否进入重分配集被移动过等信息 多重映射由于处理器可不认识地址中哪几位是真是的寻址地址哪几位是标记位所以Hotspot就通过多重映射技术对地址做一个映射将寻址地址相同标记位不同的引用都映射到同一块物理地址空间上。
ZGC收集器仅从引用上就可以判断一个对象是否处于重分配集中回收集若用户访问了重分配集中的对象将被内存屏障截获然后根据Region上的转发表将请求转发到新复制的对象上同时修正引用值使其指向新对象。
总结
收集器串行、并行或者并发新生代/老年代算法目标适用场景Serial串行新生代复制算法响应速度优先单CPU环境下Client模式Serial Old串行老生代标记-整理响应速度优先单CPU环境下Client模式、CMS的后备预案ParNew并行新生代复制算法响应速度优先多CPU环境时在Server模式与CMS配合Parallel Scavenge并行新生代复制算法吞吐量优先在后台运算而不需要太多交互的任务Parallel Old并行老生代标记-整理吞吐量优先在后台运算而不需要太多交互的任务CMS并发老生代标记-清除响应速度优先集中在互联网网站或B/S系统服务端的Java应用G1并发新生代和老年代标记-整理复制算法响应速度优先面向服务端应用将来替换CMS
拓展
GC相关的JVM参数
内存溢出
# 生产环境一般再额外增加GC日志参数OOME HeapDump 参数
-XX:HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath/path/to/dir/
#日志文件的输出路径
-Xloggc:/path/to/log/dir/gc-%t.log
-XX:PrintGCCause
#输出GC日志
-XX:PrintGC
#输出GC的详细日志
-XX:PrintGCDetails
#输出GC的时间戳以基准时间的形式
-XX:PrintGCTimeStamps
#输出GC的时间戳以日期的形式如 2013-05-04T21:53:59.2340800
-XX:PrintGCDateStamps
#在进行GC的前后打印出堆的信息
-XX:PrintHeapAtGC