JVM管理的内存中,虚拟机栈、本地方法栈和程序计数器的生命周期和线程的生命周期一致,随着栈帧的出栈实现自动的内存清理,因此JVM中需要GC的内存区域主要在Java堆和方法区。

程序所使用的对象和数组填充满Java堆之后,会抛出out of memory异常,程序挂掉,GC机制将不再使用的对象和数组删除,整理内存以便后续使用。

GC如何判断对象是否需要被回收

需要进行回收的对象的已经不再存活的对象(不再使用),判断对象是否存活的方法有:

(1)引用计数(缺点:可能存在循环引用的问题,导致GC无法回收,内存泄漏);

(2)对GC Roots对象可达(Java GC使用的方法);

GC Roots对象有

(1)方法区内 类静态属性/常量 引用的对象;

(2)堆内存中引用的对象;

(3)虚拟栈中引用的堆上的对象;

(4)本地方法栈中引用的堆上的对象;

对象回收的方法

(1)标记清理 ,标记存活的对象,将未标记的对象删除,缺点:造成内存碎片,导致内存足够但是大的内存分配失败;

(2)标记整理,删除垃圾后,将存活的对象前移整理,缺点:代价大;

(3)复制算法,将内存一分为二,GC将存活的对象复制到另一半内存中,然后前该半内存中的垃圾删除,缺点:可用空间只有原来的一半;

(4)分代收集算法,现在的JVM大多是采用这种方式,根据对象的生存周期。将堆分为新生代老年代新生代有分为一个Edan区和两个Survivor 区(E区和S区内存大小一般8:1),因此GC又分为Young GCOld GC。 在新生代中,由于对象周期短(存活对象少),因此Young GC采用复制算法,老年代里对象存活率高,因此Old GC使用标记清理或标记整理算法.

【Java 基础 17】 ​​​​​​​Java GC

如何触发GC

(1)通过System.gc();手动触发;

(2)JVM自己管理,当内存不足时,自动触发;

         1)当新生代的E区满时,触发Young GC,采用复制算法将存活对象复制到S区,并将失活的对象回收;

          2)当老年代空间不足 / 方法区空间不足 

GC收集器

古早期的GC:

【Java 基础 17】 ​​​​​​​Java GC

重点讲一下CMS收集器,极大的降低StopTheWorld时间,是服务端常用的垃圾收集器,配合PawNew使用。但是由于采用的是标记清理的算法,存在内存碎片。CMS收集器工作过程:

多次标记:

1 初次标记,标出O区的GCROOT对象和被Y区引用的对象,耗时短,工作时暂停其他线程

2 并发标记,GCRootTracing,时间长,和其他线程一起工作

3 重新标记,修正并发标记中的错误,工作时暂停其他线程

并发清理:

采用标记清除算法,定点清理内存,而不影响其他位置内存,所以可以并发进行,和其他线程一起工作

下面这张图将这种 串行GC,并行GC 以及CMS的多次标记并发清理表达的很清楚。

【Java 基础 17】 ​​​​​​​Java GC

注:图片截取自https://www.bilibili.com/video/av89885794?p=2

现代的GC:

G1 收集器:JDK9之后主流的GC收集器

G1的内存结构

G1首先在内存结构上采用了region化的方法,将堆内存划分成2000块左右的小块,每块大小1-32M(2的幂次),每块region都可以作为E、S、O以及H区(本质还是O区,存储较大对象)

【Java 基础 17】 ​​​​​​​Java GC

关于Region的一个关键:Remember Set(Rset), 记录region的对象被其他region对象的引用,目的时缩小标记时所需遍历范围。

YGC采用 标记-复制算法

OGC采用MixGC,优先回收存活对象最少的区,主要工作过程:

多次标记:

(1)初次标记:标记 GCRoots 直接引的对象和所在Region,但是与CMS不同的是,G1不止标记O区。初次标记一般和YGC同时发生。

(2)RootRegion扫描 : 标记 GCRoots所在的region到O区的引用的对象,这个过程会将S区的存活对象存到O区;

(3)并发标记:不需要STW, 并发标记整个堆,这个时候会计算每个区的存活率,如果发现某个Region中所有对象失活,将其标记为X区

(4)重新标记:短暂STW,收集 并发标记阶段 工作线程产生新的垃圾,并直接删除并发标记过程中标记的X区G1中采用了比CMS更快的初始快照算法:snapshot-at-the-beginning (SATB);

并发清理:

采用复制-清理算法,并发清除失活对象,会有STW。G1将回收区域的存活对象拷贝到新区域 并 清除Remember Sets,并发清空回收区域并把它返回到空闲区域链表中。

总结G1 收集器和其他收集器(主要是CWS)区别:

1. 内存结构不同。G1 内存结构将JVM管理的内存分成很多的小块,更灵活应用内存;

2. 增加Root Region Scanning阶段,借助Remember Set这一数据结构记录Region中对象在别的Region的引用,缩小标记遍历范围;

3. 重新标记过程中采用比CMS更快的SATB算法,且直接删除X区,提高效率;

4. MixGC优先回收对象存活率低的区,而不是全部清除,达到垃圾清理的要求且最大限度的降低STW时间,提高效率;

5. YGC和OGC均使用的是复制-清理的算法,不会造成垃圾碎片;

相关文章:

  • 2022-01-11
  • 2021-10-01
  • 2021-12-27
  • 2021-04-20
  • 2022-01-03
  • 2021-04-20
  • 2022-12-23
  • 2021-11-22
猜你喜欢
  • 2021-12-06
  • 2021-11-23
  • 2021-10-07
  • 2021-09-30
  • 2021-08-29
  • 2022-01-27
相关资源
相似解决方案