什么是自动垃圾回收?自动垃圾回收是一种在堆内存中找出哪些物件在被使用,还有哪些物件没被使用,并且将后者删掉的机制。
所谓使用中的物件(已引用物件),指的是程式中有指标指向的物件;而未使用中的物件(未引用物件),则没有被任何指标给指向,因此占用的内存也可以被回收掉。
在用 C 之类的程式语言时,程序员需要自己手动分配和释放内存。而 Java 不一样,它有垃圾回收器,释放内存由回收器负责。本文接下来将介绍垃圾回收机制的基本过程。
第一步:标记垃圾回收的第一步是标记。垃圾回收器此时会找出哪些内存在使用中,还有哪些不是。
上图中,蓝色表示已引用物件,橙色表示未引用物件。垃圾回收器要检查完所有的物件,才能知道哪些有被引用,哪些没。如果系统里所有的物件都要检查,那这一步可能会相当耗时间。
第二步:清除这一步会删掉标记出的未引用物件。
内存分配器会保留指向可用内存的引用,以供分配新物件。
压缩为了提升效能,删除了未引用物件后,还可以将剩下的已引用物件放在一起(压缩),这样就能更简单快捷地分配新物件了。
为什么需要分代垃圾收集?之前说过,逐一标记和压缩 Java 虚拟机器里的所有物件非常低效:分配的物件越多,垃圾回收需时就越久。不过,根据统计,大部分的物件,其实用没多久就不用了。
来看个例子吧。(下图中,竖轴代表已分配的字节,而横轴代表程式执行时间)
上图可见,存活(没被释放)的物件随执行时间越来越少。而图中左侧的那些峰值,也表明了大部分物件其实都挺短命的。
JVM 分代根据之前的规律,就可以用来提升 JVM 的效率了。方法是,把堆分成几个部分(就是所谓的分代),分别是新生代、老年代,以及永生代。
新物件会被分配在新生代内存。一旦新生代内存满了,就会开始对死掉的物件,进行所谓的小型垃圾回收过程。一片新生代内存里,死掉的越多,回收过程就越快;至于那些还活着的物件,此时就会老化,并最终老到进入老年代内存。
Stop the World 事件 —— 小型垃圾回收属于一种叫 Stop the World 的事件。在这种事件发生时,所有的程式执行绪都要暂停,直到事件完成(比如这里就是完成了所有回收工作)为止。
老年代用来储存长时间存活的物件。通常,设定一个阈值,当达到该年龄时,年轻代物件会被移动到老年代。最终老年代也会被回收。这个事件成为 Major GC。
Major GC 也会触发STW(Stop the World)。通常,Major GC会慢很多,因为它涉及到所有存活物件。所以,对于响应性的应用程序,应该尽量避免Major GC。还要注意,Major GC的STW的时长受年老代垃圾回收器型别的影响。
永久代包含JVM用于描述应用程序中类和方法的元资料。永久代是由JVM在执行时根据应用程序使用的类来填充的。此外,Java SE类库和方法也储存在这里。
如果JVM发现某些类不再需要,并且其他类可能需要空间,则这些类可能会被回收。
世代垃圾收集过程现在你已经理解了为什么堆被分成不同的代,现在是时候看看这些空间是如何相互作用的。 后面的图片将介绍JVM中的物件分配和老化过程。
首先,将任何新物件分配给 eden 空间。 两个 survivor 空间都是空的。
当 eden 空间填满时,会触发轻微的垃圾收集。
引用的物件被移动到第一个 survivor 空间。 清除 eden 空间时,将删除未引用的物件。
在下一次Minor GC中,Eden区也会做同样的操作。删除未被引用的物件,并将被引用的物件移动到Survivor区。然而,这里,他们被移动到了第二个Survivor区(S1)。
此外,第一个Survivor区(S0)中,在上一次Minor GC幸存的物件,会增加年龄,并被移动到S1中。待所有幸存物件都被移动到S1后,S0和Eden区都会被清空。注意,Survivor区中有了不同年龄的物件。
在下一次Minor GC中,会重复同样的操作。不过,这一次Survivor区会交换。被引用的物件移动到S0,。幸存的物件增加年龄。Eden区和S1被清空。
此幻灯片演示了 promotion。 在较小的GC之后,当老化的物体达到一定的年龄阈值(在该示例中为8)时,它们从年轻一代晋升到老一代。
随着较小的GC持续发生,物体将继续被推广到老一代空间。
所以这几乎涵盖了年轻一代的整个过程。 最终,将主要对老一代进行GC,清理并最终压缩该空间。
最后还是要推荐下小编的Java学习群:641121948,也可以加我微信:Zhanlaoshi51 不管你是小白还是大牛,小编我都欢迎,不定期分享干货,包括小编自己整理的一份2019最新的java精讲视讯入门教程,欢迎初学和进阶中的小伙伴。
每天晚上20:00都会开直播给大家分享入门学习java的知识和路线方法,群里会不定期更新最新的教程送2019java学习教程),大家都是学习技术的,或是兴趣,或是大学生,还有工作中想提升自己能力的朋友,如果你是正在学习java的小伙伴可以加入学习。最后祝所有爱好者都能够走上人生巅峰,让程式码将梦想照进现实,非常适合新手学习,有不懂的问题可以随时问我,工作不忙的时候希望可以给大家解惑。