GC算法

112 阅读4分钟

JVM新生代使用的是Mark-Copy算法,Serial垃圾回收器,采用串行单线程完成GC, PS垃圾回收器在年老代上采用的垃圾回收算法可以看作是标记-清除算法标记-压缩算法的结合体。

java -XX:+PrintCommandLineFlags -version 查看jvm使用的垃圾回收器

minor gc:未成年 major gc:成年 首先,新对象的内存分配都是先在Eden区域中进行的,当Eden区域的空间不足于分配新对象时,就会触发年轻代上的垃圾回收(发生在Eden和Survivor内存区域上),我们称之为"minor garbage collection".同时,每个对象都有一个“年龄”,这个年龄实际上指的就是该对象经历过的minor gc的次数。如图1所示,当对象刚分配到Eden区域时,对象的年龄为“0”,当minor gc被触发后,所有存活的对象(仍然可达对象)会被拷贝到其中一个Survivor区域,同时年龄增长为“1”。并清除整个Eden内存区域中的非可达对象。 当第二次minor gc被触发时(如图2所示),JVM会通过Mark算法找出所有在Eden内存区域和Survivor1内存区域存活的对象,并将他们拷贝到新的Survivor2内存区域(这也就是为什么需要两个大小一样的Survivor区域的原因),同时对象的年龄加1. 最后,清除所有在Eden内存区域和Survivor1内存区域的非可达对象。 当对象的年龄足够大(这个年龄可以通过JVM参数进行指定,这里假定是2),当minor gc再次发生时,它会从Survivor内存区域中升级到年老代中,如图3所示。 其实,即使对象的年龄不够大,但是Survivor内存区域中没有足够的空间来容纳从Eden升级过来的对象时,也会有部分对象直接升级到Tenured内存区域中。

问答

Q:可达性分析a与b互为引用,这不是死循环了吗,为什么能被回收的 因为可达性分析只标记可达的,如果a和b都不可达,那么可达性分析标记不到,就当成垃圾回收了。

Q:对于为什么需要stw机制的解释还是有的困惑。假如一个对象已经被标记为垃圾了,其它线程怎么还会有机会引用它呢?就算通过stw,把它标记并回收了,那想引用它的线程重新恢复执行了会发生什么? GC标记的是活着的(能够被引用到的)对象,剩下的是垃圾。如果没有STW,其他线程在垃圾回收过程中产生了垃圾(某对象不再被引用),那么会被漏掉。

Q:为什么非要停止程序的运行呢?

这个其实也不难理解,假设我们的程序与GC线程是一起运行的,各位试想这样一种场景。

假设我们刚标记完图中最右边的那个对象,暂且记为A,结果此时在程序当中又new了一个新对象B,且A对象可以到达B对象。但是由于此时A对象已经标记结束,B对象此时的标记位依然是0,因为它错过了标记阶段。因此当接下来轮到清除阶段的时候,新对象B将会被苦逼的清除掉。如此一来,不难想象结果,GC线程将会导致程序无法正常工作。

上面的结果当然令人无法接受,我们刚new了一个对象,结果经过一次GC,忽然变成null了,这还怎么玩?

============= 标记-清除算法、STW的来历 Java垃圾回收机制 minor gc 会发生stop the world 现象吗? - wuxinliulei的回答 - 知乎 www.zhihu.com/question/29…

  1. 复制算法 一般用于新生代
  2. 标记整理
  3. 标记清除算法

垃圾收集器类型 blog.csdn.net/tjiyu/artic… crowhawk.github.io/2017/08/15/…

java的gc为什么要分代? - RednaxelaFX的回答 - 知乎 www.zhihu.com/question/53…

GC Root blog.csdn.net/calledWWW/a…

【证】:那些可作为GC Roots的对象 blog.csdn.net/u010798968/…

面试官,为什么总是问我这些 JVM 问题?文章集合 mp.weixin.qq.com/s/9pSlfzzas…

Java垃圾回收机制

blog.csdn.net/chenleixing…

FullGC minor GC

blog.csdn.net/renfufei/ar… blog.csdn.net/xuyukun121/…

ZGC mp.weixin.qq.com/s/40YZYXuje… mp.weixin.qq.com/s/9-NFMt4I9…