Java-垃圾回收

1、 Java GC堆内存分配。

2、晋升年龄(默认是15岁,Hotspot是动态年龄判定,遍历所有对象,按照年龄从小到大对其占用的大小进行累积,当累积到某个年龄超过了survivor的50%取这个年龄为晋升阈值。)

 

 

GCRoot对象

1、虚拟机方法栈(栈帧中的本地变量表)中的引用变量。

2、本地方法栈中的引用变量。

3、方法区中静态属性的引用对象。

4、方法区中常量引用的对象。

5、所有被同步锁持有的对象。

 方法区中存储了:1、类信息(包括了JVM加载类型:类class、接口interface、枚举enum)、直接父类的完整有效名称、类型修饰符2、成员变量信息3、静态变量4、运行时常量池:各种字面量和类型等引用。

 加入eden和from都有对象,那么将这两个地方的对象都复制到to区,然后交换from和to。

 

GC规模

1、MinorGC发生在新生代的垃圾回收,暂停时间短

2、MixedGC新生代+老年代部分区域的垃圾回收,G1收集器特有

3、FullGC新生代+老年代 完整垃圾回收,暂停时间长,尽力避免

 

 

 

1.1对象优先在eden区分配

大多数情况下,对象在新生代中eden区分配,当eden没有足够多空间分配的时候,虚拟机将发起一次MinorGC

 

针对HotSpotVM的实现,里面的GC主要分为两大种:

部分收集(PartialGC)

  1、新生代收集(MinorGC/Younggc):只对新生代进行垃圾收集 

  2、老年代收集(MajorGC/OldGC):只对老年代进行垃圾回收,需要注意的是MajorGC在有语境中也用于指代整堆收集

  3、混合收集(MixedGC):对整个新生代和部分老年代进行垃圾收集

整堆收集(Full GC):对整个JAVA堆和方法区收集。

 ConcurrentMarkSweepGC(CMS)

1、old并发标记,重新标记时需要STW,并发清除

2、failback full gc 

3、缺点会有内存碎片

4、注重响应时间

 

二、垃圾回收器

 

 

7种垃圾收集器与垃圾分代之间的关系

 

 

 

 

 

 

 

Parallel GC(吞吐量优先 )

1、eden内存不足发生MinorGC,标记复制STW不会有碎片

2、old内存不足发生FullGC,标记整理STW不会有碎片),暂停时间更长,因为要完整的回收。  

3、注重吞吐量。(比如消息队列的消息传过来后涉及大量的计算,而不是立即与用户做交互,工资支付,科学计算等)

 

在吞吐量优先的场景,paralle收集器与parallelold收集器的组合,在server模式下内存回收性能不错。二者是相互激活的  

可以设置的参数

最大停止时间、使用自适应调优策略。

 

 互联网请求尽量不要暂停。

大量计算响应时间,响应时间久一点,但是整体上时间短就行。

 

 

 JDK8 默认使用的是Parallel Scavenge

 

垃圾回收器:

ConcurrentMarkSweep GC (CMS)(用的三色标记算法 黑灰白,标记两次,因为在第一次标记的完后,用户线程可能更改引用,然后进行第二次标记,第二次标记不会被清理,只有第二次cms才会清理)

1、old并发标记,重新标记时需要STW,并发清除 (会存在内存碎片)

2、Failback full gc

3、注重响应时间。 并发导致线程去做垃圾对象标记,所以吞吐量会变低。 

 

 

弊端:

 并发标记的时候,用户线程将有些标记为黑色的对象,变成灰色,但是下次重新标记会不扫描他们,导致产生浮动垃圾。

 

 

参数使用  手动指定cms收集器,  -XX:+useConcMarkSweepGC、设置CMS线程数。

 

 

jdk9以后  G1GC(以后默认的垃圾回收器,在保证吞吐量优先的情况下,降低停顿时间)

局部是复制算法,在整体是标记整理算法。

优势:

1、并行和并发

2、 

3、

 

 1、并发与并行:在多核环境下能够使用多个CPU来缩短STW的停顿时间。部分其他收集器原本需要停顿java线程,执行GC动作,G1收集器仍然可以通过并发方式让java继续执行。

 2、分代收集:虽然G1可以不需要其他收集器就能独立管理整个GC堆,但是还是保留了分代回收

 3、空间整合:与CMS的“标记-清理”算法不同,G1从整体来看是基于“标记-整理”算法实现的收集器。从局部看是标记复制

 4、可预测的停顿:G1的优势,降低停顿时间是CMS和G1共同关注的,但G1追求停顿的外,还可以建立可预测的时间模型,使使用者明确指定长度M毫秒时间内。

垃圾回收步骤:

  1、初始标记

  2、并发回收

  3、最终标记

  4、筛选回收

  G1收集器在后台维护了一个优先列表,每次根据允许的收集时间,优选选择回收价值最大的Region。这种Region划分内存空间以及有优先级的区域回收方式,保证了G1收集器在有限时间内尽可能收集更多内存。

 

 

 

 

 优势:

  

 

 eden区回收复制到Survivor区 

 

 从经验来说,小内存应用上CMS的表现大概率会高于G1,G1在大内存应用上发挥起优势。 

CMS需要额外的空间,额外负载,rset来记忆,避免全局扫描。

 

 

G1回收期场景操作步骤
1、开启G1垃圾收集器

2、设置堆的最大内存

3、设置最大的停顿时间

 

回收过程:

1、年轻代GC minor gc

2、老年代并发标记 

3、混合回收mixed gc(全部新生代和部分老年代,部分老年代根据回收价值绝对那个先回收)

如果需要针对GC评估失败,提供一种失败保护机制,即强力回收。

 

 

G1垃圾回收期具体过程:

1、

 

2、

 

 

 

 

 

 

1、响应时间与吞吐量兼顾

2、划分多个区域每个区域可以充当eden survivor humongous

3、新生代回收:eden内存不足,标记复制 stw

4、并发标记:old并发标记,重新标记需要stw

5、混合收集:并发标记完成,开始混合收集,参与复制的eden、survivor、old,其中old会根据暂停时间目标,选择回收价值高的区域,复制时STW

6、failback full gc

 

 

Serial回收器:串行回收

最基本最老的收集器。采用的复制算法、串行回收和stw机制进行内存回收。

 

 

 总结:

这种垃圾收集器,现在不用串行的了,而且在限定单核cpu才可以用,对于交互性强的应用而言,这种垃圾收集器是不能接收的。一般在javaweb应用程序中是不会采用串行垃圾收集器的。

 

ParNew回收期

除了收集器采用的是并行回收的方式以外,两款垃圾收集器几乎没有任何区别。parnew同样也是采用复制算法,“stop the world”机制

parnew 是很多jvm运行在server模式下新生代的默认垃圾收集器。

 

 

 

 

 

 

 

小结:

如果想要最小化地使用内存和并行开销,选Serial GC;

如果想要最大化地应用程序,选Parallel GC

如果想要最小化GC中断或者停顿时间,选CMS GC

 

判断对象死亡:

1.1引用计数法:(目前基本不用了)

如果对象有引用就不是死亡,但是会出现循环引用的现象。回收不了

1.2可达性分析算法

基本思想:通过一系列的GCRoots的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到GC Roots每页任何引用链引用的话,则需要回收

那些对象可以作为GC Roots呢?

1、虚拟机栈(栈帧的本地变量表)中的引用对象。

2、本地方法栈(Native 方法)中引用的对象

3、方法区中类静态属性引用的对象

4、方法区中常量引用的对象

5、所有被同步锁持有的对象

 

三、对象可以被回收,就一定可以被回收吗?

即使在可达性分析法中不可达的对象,也并非是非死不可的,因为可能处于缓刑状态,真正宣告一个对象死亡,

至少要经历两次标记过程;可达性分析法中不可达的对象被第一次标记并且进行筛选,筛选的条件是次对象是是否有必要

执行finalize的方法。当对象没有覆盖finalize方法,或者finalize方法已经被虚拟机调用过的时候,虚拟机将这两种情况视为没有必要执行。

 

被判定为需要执行的对象将会被放在一个队列中进行第二次标记,除非这个对象与引用链上的任何一个对象建立了联系,否则就会真的被回收。

finalize方法弊端(每个类都有finalizer,它不能被直接调用,而被jvm在适当的时候调用,作为一种收尾机制):

1、行为不稳定

2、降低性能

3、可移植性低

(使用finalizer最严重的缺点是不能保证被执行,一个对象变得不可达开始,一直到该对象被jvm终结,过程中时间是未知的。当一个类提供了finalizer,会查看finalizer队列是否很多实例等待被终结。

     

 

面试题:说说GC和分代回收算法

GC目的在与实现无用对象内存自动释放,减少内存碎片、加快分配速度。

GC要点:

1、回收区域是堆内存,不包括虚拟机栈,在方法调用结束会自动释放方法占用的内存

2、判断无用对象,使用可达性分析算法三色标记法标记存活对象,回收未标记的对象

3、GC具体的实现称为垃圾回收器(G1,CMS,PC)

4、GC大都采用分代回收思想,理论依据大部分朝生夕灭,用完立刻就会回收,另有少部分对象会长时间存活,

每次很难回收,根据这类对象特性分为新生代老年代,不同区域回收策略不同。

5、根据GC规模可以分为MinorGC,MixedGC,Full GC(老年代不足)

 

 

三色标记与并发漏标问题

1、用三种颜色记录对象的标记状态

1.1 黑色-已标记(沿着根对象的引用链找到了这个对象,并且这个对象内部其他引用都处理完了)

1.2 灰色-标记中(沿着根对象的引用链找到了这个对象,但是这个对象内部其他引用未被处理)

1.3 白色-未被标记(未被处理)

 

 三色标记与并发漏标问题

产生漏标问题-记录标记过程中的变化

 

 

 解决方案:

1、increment update

  1.1只要发生了赋值,被赋值的对象就 会被记录(变为灰色)

2、Snapshot at the beginning satb

  2.1新对象会被记录

  2.2被删除引用关系的对象也会被记录

 

 

评估GC的性能指标

 

1、吞吐量 a/(a+b)

2、垃圾收集开销:b/(a+b)

3、暂停时间:执行垃圾收集时,程序工作被暂停的时间。

4、收集频率:相对于应用程序执行,收集操作发生的频率。 (频率低可能会造成暂停时间长,频率高,暂停时间短)

5、内存占用:Java堆区所占的内存大小

6、快速:一个对象从诞生到回收经历的时间。

标记的这个三个构成了“不可能三角”。

主要关注(吞吐量、暂停时间)

高吞吐量的应用程序有更长的时间基准,快速响应是不必考虑的。

 

 

垃圾回收器总结:

 

 Serial=>parallel并行=>cms(并发)=>G1=>ZGC

 

  

 

posted @ 2022-05-06 12:47  雷雷提  阅读(102)  评论(0编辑  收藏  举报