JAVA虚拟机学习记录数据(五)垃圾回收
JAVA虚拟机学习记录数据(五)垃圾回收
为什么需要GC?

垃圾回收算法,java里没有引用计数算法,9和X也属清除阶段的


引用计数算法:
可达性分析算法:


GC root包含哪些?

https://blog.csdn.net/u010798968/article/details/72835255
标记-清除算法:从gc root遍历所有对象,标记可达对象,即存活对象,然后再遍历所有的对象(过程为下图的蓝色横线),清除垃圾对象。


标记清除算法缺点:效率不高,因为需要从头遍历。清除的意思是,把上图黑色的垃圾对象的内存地址保存在空闲列表,下次有新的对象时,将黑色的块覆盖了,并不是将黑色块置空。

复制算法,准备B区,A区开始,从GC roots开始遍历,遍历到可达的对象复制到B区,S1区和S2区就用到了复制算法,S区的对象大多朝生夕死。


复制算法优点:没有标记清除过程,高效,复制后保证空间的连续性,没有碎片问题。
复制算法缺点:需要内存空间大,复制后需要维护新的引用关系。而且如果系统存活的对象多和垃圾少,需要复制很多对象,会使效率低。因此适用于新生代。
标记压缩算法



对比三种算法

对比发现,没有完美的算法。
因此会采用分代收集的思想。



增量收集算法:


分区算法:

以G1为例,H是大对象


内存溢出:

内存泄漏:
STW(STOP THE WORLD)


GC的并发与并行:



安全点与安全区域:

垃圾回收器概述:



垃圾回收器的分类:

64位默认都是Serve模式。


compact压缩整理,即前文提到的,垃圾回收后进行碎片化地整理

GC的性能指标:重点看标红的三个,这三个不可能都满足。




注重吞吐量:(200ms+200ms)/6000ms
主动低延迟:100ms




七款经典收集器与垃圾分代之间的关系,G1年轻代和老年代都可以。

垃圾回收器组合使用

Serial回收器:串行回收

Serial回收器图示:


ParNew回收器:并行回收,该回收器就是Serial回收器的并行版本,STW时间较短

图示,新生代使用ParNew,老年代使用Serial Old


Parallel Scavenge回收器,吞吐量优先



Parallel Scavenge回收器参数设置:

-XX:MaxGCPauseMillis和-XX:GCTimeRatio,是此消彼长的。举例说明,MaxGCPauseMillis设置为10ms,即STW时间短,可能回收器会把堆内存调小,这样stw时间就短,设置为50ms,堆内存就调大,stw时间长,但是stw时间短了的话,stw频率会上升,stw时间乘以频率,总的时间就上去了,导致总的吞吐量就降低。GCTimeRatio是式子里的N,如果设置为19,那么垃圾收集时间为1/20=5%

UseAdaptiveSizePolicy参数是默认开启的

CMS回收器:注重相应时间,即低延迟。


CMS工作原理:初始标记(会STW时间很短),可以理解为先找第一层的对象,并发标记(不会STW),重新标记(会STW,时间较长),可以理解为从初始标记的第一层对象开始遍历,层层遍历,想象成对象树。重新标记,由于并发标记阶段有些对象发生了变化,可能漏标(有的对象刚创建出来,需要标上)、错标(本来是存活的,用户线程把它变为不存活了)



当堆内存的使用率达到一定阈值时,便开始回收,因为其并发性,比如并发标记时,用户线程同时执行着,很有可能会产生心的对象,可能就会内存溢出。


补充下图的解释:并发清理时,用户线程也在执行,如果整理内存,即移动对象(如下下图所示),会改变对象的地址,很可能会修改了线程产生的对象的地址。


CMS收集器的优缺点,
第一点补充解释:Full GC了,临时启用Serial Old收集器很可能导致系统;卡顿第二点的解释:如下面的图示,比如并发标记阶段,有四条线程,其中一条要分出来并发标记。
第三点,浮动垃圾,比如,并发清理过程中,用户线程产生了对象,并且这些对象马上不再使用了,需要下次GC时再来清理。


CMS可设置的参数

小结:

G1收集器,区域分代化。价值大小的解释:划分了若干个区域,比如A、B、C,回收A区时,发现使用率高且可达对象多,那么回收得到的空闲区域小,回收价值高,B区基本都是垃圾,价值低。这么就可以维护一个优先列表。


优势:


比如,设置了10毫秒,那么有较大的概率,回收器能在10毫秒内回收完垃圾

劣势:

举例说明,比如某个E区被整个回收后,可以充当O区,但是某个区不能既是E区又是O区

分区Region:化整为零

H区举例,区域设置为4MB,有一个对象是7MB,那么就放H区

连续的H区,比如是上图中占了三个格子的H区

温习前面所学的内存分配的过程,一个region是怎么分配的。指针碰撞、TLAB

G1回收垃圾的过程,主要是前三点,第四点是补充的。第四点解释,比如用户线程创建对象,占用空间的速度大于回收的速度时,内存越来越不足。

下图并发标记是老年代并发标记。

独占式(STW),过程跟之前的相似,清空eden区,S1、S2互相搬来搬去,老年代的回收,在满足暂停时间(比如200ms)下,挑选价值高的回收,一定值可以通过InitiatingHeapOccupancyPercent设置

G1回收器的参数设置:
第二点补充解释,范围是指1、2、4、8、16、32MB,总堆空间大小2GB至64GB。
第三点补充解释,如果设置的比较小,比如20ms,维护的列表里,A区回收要花费20毫秒、B区20毫秒、C区40毫秒、D区50毫秒,那么回收器只会回收A区B区,回收的区域就少了,然后用户线程产生的对象越来越多,最终导致full GC,也有可能内存溢出。
第五点补充解释,即占第四条提到的线程数的四分之一。


G1回收器适用的场景:

浙公网安备 33010602011771号