JVM 垃圾回收的问题

Posted 小程学Java

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM 垃圾回收的问题相关的知识,希望对你有一定的参考价值。

 阅读本文大概需要5分钟



面试有时候会被问到垃圾回收的问题,于是前段时间我就专门挑了本书看,感觉还不错,就是那本「深入理解 Java 虚拟机」,整理了一下内容



01

判断哪些对象已经“死去”?


引用计数算法:

给对象添加一个引用计数器,有引用,值+1,引用失效时,值-1。当值等于0时,则不引用对象,可以处理了,这是一个常见的算法,在一些脚本语言的领域使用较多,但是JVM里很少有使用,原因是,不能解决对象之间相互循环引用的问题,无法将仅相互引用得对象进行回收


可达性分析算法:

通过一系列的称为 ”GC Roots“ 的对象作为起始点,从这些节点往下搜索,搜索走过的路径被称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,证明其是不可用的( GC Roots 到该对象不可达)



02


生存还是死亡(两次标记)


GC root 不可达的对象,并非 ”非死不可的“,要真正宣告对象的死亡,至少经历两次标记过程;


如果对象没有与GC Roots 相连的引用链,那他将会被第一次标记并进行一次筛选,筛选的条件是此对象是否有必要执行finalize方法,若对象没有覆盖该方法,或者该方法已经被虚拟机调用过,虚拟机将这两种情况都视为没有必要执行。


如果这个对象被判定有必要执行finalize方法,那么这个对象会被放置在队列中,稍后 GC 将对队列中的对象进行第二次小规模的标记。该对象只要重新与引用链上的任一个对象建立关联,即可成功拯救自己。




03


四种引用


强引用:比如 Object obj = new Object();,强引用在,永不回收


软引用:  有用非必须的对象,在内存溢出前,会将它们列入回收范围二次回收,若还没足够内存,才抛出内存溢出异常


弱引用: 非必需得对象,垃圾回收时,无论内存够不够,都会将其回收掉


虚引用: 最弱的引用,是否被虚引用,对对象的生存时间不影响




04


什么时候触发 GC


新生代Eden区满了,发起 Minor GC(新生代GC),MinorGC非常频繁,回收速度较快


老年代的对象大于老年代的剩余空间,触发Full GC,经常会伴随着一次Minor GC;Full GC甚至会比Minor GC慢十倍以上




05


GC 做了什么


让我来介绍一下 GC 的几种垃圾回收方式


标记清理:

将不用的对象标记后清理 ;内存碎片太多


复制清理:

新生代常用 复制算法进行GC

将可用内存分为等量的两块,每次仅用一块,这一块用完后,将还存活的对象复制到另一块上,再将已使用的一次清理掉,这样每次都是对半区进行内存回收,只需移动堆顶指针,运行高效,只是可用内存缩小一半。


因为新生代的对象很多 「朝生夕死」 ,所以不需要1:1分配,分出一份较大的 Eden 区和两份较小的 Survior(生存者)区即可,每次回收时将 Eden 和一份 Survior ,转移到另一份 Survior 区中。当空间不够时,向老年代进行分配担保,多余的对象进入老年代


标记整理:

老年代 常用 标记整理算法进行 GC

老年代的对象存活率较高,如果还使用复制算法就会造成「内存的过多浪费」,所以使用一种新的方法:将所有需要回收的对象,进行标记,让所有存活的对象向一边移动,然后清理掉端边界以外的内存。



以上是关于JVM 垃圾回收的问题的主要内容,如果未能解决你的问题,请参考以下文章

如何修改jvm虚拟机垃圾回收器

JVM专题--垃圾回收算法, 垃圾回收器

JVM—— 垃圾回收

JVM的垃圾回收机制 总结(垃圾收集回收算法垃圾回收器)

谈谈JVM垃圾回收机制及垃圾回收算法

JVM垃圾回收器