点击下方关注我,然后右上角点击...“设为星标”,就能第一时间收到更新推送啦~~~
垃圾回收(Garbage Collect)是Java语言中的一种自动内存管理机制,用于自动回收不再使用的对象所占用的内存空间。Java虚拟机会自动追踪和识别不再使用的对象,并将其回收,以释放内存资源。垃圾回收的主要目的是自动管理内存,以避免内存泄漏和内存溢出等问题。
1
Java中的垃圾回收机制
Java中的垃圾回收机制通过以下步骤进行:
标记(Mark):标记所有被引用的对象,标记结束后,未被标记的对象将被视为垃圾。
清扫(Sweep):回收垃圾对象,将垃圾对象从内存中清除。
整理(Compact):移动活对象,将活对象从原地移到新的位置,以便后续的存储。
再次标记(Mark):经过移动后,重新标记所有活对象,确保它们的引用关系正确。
再次清扫(Sweep):再次清理未被标记的对象。
Java中的垃圾回收器是并发执行的工作线程,它们在后台运行,并自动触发。
通过标记过程来确定一个对象是垃圾,标记所有被引用的对象,标记结束后,未被标记的对象将被视为垃圾。只要在标记阶段被标记的对象,在后续的程序执行过程中就不会被修改,那么它们就是垃圾,等待回收。标记主要有 2 种方法。
1、引用计数法
在对象中设置一个引用计数器,每当有一个地方引用它时,计数器值就加 1,引用失效时就减 1。对于一个对象而言,任何时刻计数器为 0 的对象就是不可能再被使用的,就说明该对象是垃圾。如果两个对象相互持有引用,也就是两个对象的计数器都不为 0 ,就无法通知GC收集器回收它们,这两个对象就永远不能被回收。因此在 JVM 中一般不会用它来判断对象是否存活。
2、可达性分析
通过一些 GC Roots 对象(类加载器、虚拟机栈的本地变量表、static 成员、常量引用、本地方法栈的变量、Thread等)开始向下搜索,当没有被 GC Roots 引用到的对象就可以进行回收,下图的 Object4 和 Object5 没有被GC Roots 引用,因此就可判断为可回收对象。
2
垃圾收集算法
垃圾收集算法主要有 4 种。
1、复制算法(Copying)
将内存划分为两块相等的区域,每次只使用其中一块,当进行 GC 的时候,就将还存活的对象复制到另外一块上面,然后把已经使用过的内存空间一次性清空。比如 S0 和 S1。
2、标记-清理算法(Mark-Sweep)
标记:当进行 GC时,所有的对象都会被扫描一遍,找出内存中需要回收的对象,并且把它们标记出来,从而确定需要垃圾回收的对象。标记的过程就是利用可达性分析找到垃圾对象。
清理:在标记完成之后统一清理掉被标记需要回收的对象,回收所有标记过的对象,释放出对应的内存空间。
标记清理算法的缺点:标记清理过程比较耗时,标记清理之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
3、标记-整理算法(Mark-Compact)
标记过程仍然与"标记-清理"算法一样,但是后续步骤不是直接对可回收对象进行清理,而是空间进行整理,整理的过程是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。
4、分层算法
将内存分为多个层次,每个层次都有不同的存活对象比例,越上面的层次,存活对象比例越高。
3
堆中的垃圾收集算法使用
在堆内存中主要是利用分代来使用不同的垃圾收集算法的,在 Young 区使用复制算法,因为绝大多数的对象在被分配之后生命周期比较短,在Young 区使用复制效率比较高。在 Old 区使用标记清除或者标记整理算法,因为 Old 区对象的生命周期比较长,对象存活时间比较长复制就没有意义了,标记以后再清理或者整理效果高。
后面将为大家介绍垃圾收集器。