Java垃圾收集机制

这篇具有很好参考价值的文章主要介绍了Java垃圾收集机制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

判断对象是否存活

引用计数算法

可达性分析算法

GC Root的产生

Java中的四种引用类型

1.强引用

强引用弱化方式

方式1:使对象指向null

方式2:使对象超出作用域范围

2.软引用

3.弱引用

4.虚引用

垃圾收集算法

分代收集理论

垃圾收集算法分类

1.标记-清除算法(Mark-Sweep)

标记-清除算法的特点或问题

2.标记-复制算法(Copying)

算法工作流程

标记-复制算法的特点

3.标记-整理算法(Mark-Compact)

算法工作流程

标记-整理算法的特点

总结

前言

Java中的垃圾收集器(Garbage Collector)负责管理堆内存中的对象,回收不再使用的对象以释放内存空间。

判断对象是否存活

垃圾收集器工作的前提是该对象确实为一个垃圾对象,因此在 回收前需要进行判断,这里有两种方式可以对对象进行判断,分别是引用计数算法和可达性分析算法

引用计数算法

引用计数算法是通过在对象中添加一个引用计数器,来记录该对象被其他对象引用的次数,当计数器为0的时候,表示该对象没有被其他对象引用,是一个可回收的垃圾对象。

当然,这种算法存在一个较明显的问题,就是无法应对对象的循环引用,例如a 对象引用了 b 对象,b 对象也引用了 a 对象,ab 对象却没有再被其他对象所引用了,其实正常来说这两个对象已经是垃圾了,因为没有其他对象在使用了,但是计数器内的数值却不是 0,所以引用计数算法就无法回收它们。

Java垃圾收集机制,jvm,java,开发语言

可达性分析算法

可达性分析算法是通过引用链确认对象是否可用,也就是说在引用链上的对象即为可用对象,否则为垃圾对象。在该引用链上定义了“GC Root”起始节点集,引用链上的每个对象都可以通过GC Root找到。

例如下图中,Object 6Object 7Object 8彼此之前有引用关系,但是没有与"GC Roots"相连,那么就会被当做垃圾所回收。

Java垃圾收集机制,jvm,java,开发语言

GC Root的产生
  1. 栈帧中的本地变量和参数:正在执行的方法中的本地变量和参数可以作为GC Root,因为它们是当前线程活动的一部分。
  2. 静态变量:类的静态变量通常存储在方法区中,它们随着类的加载而被创建,并且在整个程序运行期间一直存在,因此它们被视为GC Root。
  3. 虚拟机内部的特殊引用:例如常量引用、系统类加载器等。
  4. JNI引用:在Java代码中使用了JNI(Java Native Interface)时,如果在本地代码中使用全局引用或弱全局引用,它们也会作为GC Root。

Java中的四种引用类型

垃圾回收器的工作时机除了与本身使用的算法相关,还与对象本身的引用类型相关。

1.强引用

强引用是最常使用的引用,通常是指向new 出来的对象的引用 例如 Object strongReference = new Object();,对于强引用,垃圾回收器是绝对不会进行回收操作的。就算是在内存空间不足的情况下,JVM也会通过抛出OutOfMemory来终止程序,而非回收强引用。

强引用弱化方式

强引用对象也存在不使用的情况,它的回收需要通过弱化,从而使垃圾回收器回收

方式1:使对象指向null

此时垃圾回收器会认为该对象不存在引用,然后根据GC算法对该对象进行回收。

例如:ArrayList集合的clear方法,就是通过遍历数组,将数组中的每个引用都指向null,使垃圾回收器能够对对象进行回收,达到清空的效果。

Java垃圾收集机制,jvm,java,开发语言

方式2:使对象超出作用域范围

在Java中,对象的作用域通常由大括号({})来定义,包括类、方法和代码块。当对象的作用域结束时,即离开了其定义的代码块或方法,该对象就会超出其作用域范围。

简单来说就是当一个对象在其作用域内被创建时,在该作用域范围内,可以通过引用来访问和操作该对象。但是一旦离开了对象的作用域,该对象就不能再通过原有的引用来访问和操作了。比如说对象对象定义在方法内,当方法执行结束,JVM方法栈中的活动栈帧弹出时,该对象也就不在作用域范围内了。

2.软引用

软引用也是一种较强的引用类型,与强引用的不回收不同,软引用可以在内存空间补不足时被垃圾回收器回收。通常用于内存敏感内容的高速缓存。

举个例子,在下图中,模拟了一个软引用,分别测试内存溢出与内存不溢出的情况下,断开引用后,软引用中的值

Java垃圾收集机制,jvm,java,开发语言

内存充沛

Java垃圾收集机制,jvm,java,开发语言

内存不足

Java垃圾收集机制,jvm,java,开发语言

在上面的例子上我们可以看到,当内存充足的情况下,即使软引用指向null,也不会被回收,一旦内存不足,软引用则被回收。

3.弱引用

弱引用是一种比软引用更弱的引用类型,与软引用不同,弱引用在下一次垃圾回收时一定会被垃圾回收器回收,无论内存是否充足。

Java垃圾收集机制,jvm,java,开发语言

Java垃圾收集机制,jvm,java,开发语言

4.虚引用

虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用,完全不会对其生存时间构成影响,它就和没有任何引用一样,随时可能会被回收。主要用来跟踪对象被垃圾回收的活动,可以在垃圾收集时收到一个系统通知。

JDK1.2 之后,用 PhantomReference类来表示,通过查看这个类的源码,发现它只有一个构造函数和一个 get() 方法,而且它的 get() 方法仅仅是返回一个null,也就是说将永远无法通过虚引用来获取对象。

Java垃圾收集机制,jvm,java,开发语言

垃圾收集算法

说到垃圾收集算法就不得不说一个重要理论,即分代收集理论。下文详细介绍:

分代收集理论

分代收集理论基于一个观察:将对象的生命周期通常可以被划分为不同的阶段或代。根据对象的生命周期,垃圾回收器可以将内存划分为不同的代,然后针对不同代的对象应用不同的垃圾回收策略。目前主流JVM的垃圾收集器都遵循分代收集理论。

一般来说,分代收集理论将内存划分为至少两个代:年轻代、老年代

这是由于大部分对象在被创建后一段时间内会被频繁使用,但随着时间的推移,它们的生命周期会逐渐延长。因此,分代收集理论认为大部分对象是临时的,并且在它们的年轻阶段就会被回收,而只有部分对象会存活更久并进入老年代。

年轻代

被创建后一段时间内会被频繁使用,但随着时间的推移,它们的生命周期会逐渐延长。因此,分代收集理论认为大部分对象是临时的,并且在它们的年轻阶段就会被回收,而只有部分对象会存活更久并进入老年代。

老年代

在老年代中,垃圾回收器采用更长的回收周期和较少的垃圾回收操作。这是因为老年代中的对象通常具有较长的生命周期,并且相对稳定。典型的垃圾回收策略是标记-清除(Mark-Sweep)或标记-压缩(Mark-Compact)算法,其中垃圾回收器会标记并清除或压缩无效的对象,并回收相应的内存空间。

垃圾收集算法分类

1.标记-清除算法(Mark-Sweep)

标记-清除算法的整个工作过程可以分为两个阶段,分别是“标记”和“清除”。在标记阶段,首先垃圾收集器会标记出所有不需要回收的对象(这可以通过在对象的头部添加一个标记位来实现),然后进入清除阶段,将未标记的对象回收。

Java垃圾收集机制,jvm,java,开发语言

标记-清除算法的特点或问题

A.效率问题:

如果执行垃圾收集的区域中,大部分对象是需要被回收的,则需要哦执行大量的标记和清除操作,导致效率变低。

B.内存空间问题:

标记清除后会产生大量不连续的碎片,空间碎片太多,会导致分配较大对象时,无法找到足够的连续空间,从而会触发新的垃圾收集动作。

C.暂停时间:

在标记和清除阶段中,垃圾回收器需要停止应用程序的执行,这可能导致较长的停顿时间,影响应用的响应性。

2.标记-复制算法(Copying)

标记-复制算法在内存上的维护上,将空间分成两个大小相同的区域,通常称为对象区域和空闲区域。

算法工作流程
  1. 初始化时,所有对象都在对象区域。
  2. 从根对象开始,标记所有可达对象,将其从对象区域复制到空闲区域,并在新位置上更新引用。
  3. 完成复制后,对象区域中所有未被复制的对象都被认为是垃圾。
  4. 清空对象区域,并将空闲区域与对象区域交换,使空闲区域变为下一次垃圾回收的对象区域。
  5. 重复上述过程,进行下一轮的垃圾回收。

Java垃圾收集机制,jvm,java,开发语言

标记-复制算法的特点

A.高效的分配:

由于复制过程中对象是连续存放的,新对象的分配只需要简单的移动指针,效率较高。

B.暂停时间可控:

由于只需要复制存活对象,标记阶段的垃圾回收工作量相对较小,可以有效限制暂停时间。

C.内存利用率相对较低:

标记-复制算法会将堆内存的一半用于复制存活对象,因此相对于标记-清除算法会有一定的内存浪费。

D.效率降低

在对象存活率较高的情况下,需要进行较多内存间复制,导致效率降低

3.标记-整理算法(Mark-Compact)

标记-整理算法的主要思想是在标记阶段标记所有可达对象,并在标记完成后进行整理。整理阶段会将存活的对象向一端移动,然后清理掉边界之外的无效对象,以达到内存整理的目的。

算法工作流程
  1. 从根对象开始,标记所有可达对象。
  2. 在标记完成后,将存活对象向一端移动,并保持它们的相对顺序不变。这样,所有存活对象就在内存的一段连续区域中。
  3. 在移动过程中,将无效对象所占用的内存空间进行回收。可以通过向移动后存活对象的新位置复制数据来完成这一步骤。
  4. 清理掉边界之外的无效对象所占用的内存空间,使其变为可用于分配新对象的空闲内存。
  5. Java垃圾收集机制,jvm,java,开发语言

标记-整理算法的特点

A.解决内存碎片化:

通过将存活对象移动到一端,并清理边界之外的无效对象,可以实现内存的整理,解决内存碎片问题。

B.高效的分配:

由于整理后存活对象在一段连续区域中,新对象的分配只需要简单的移动指针,效率较高。

C.暂停时间可控:

标记-整理算法的标记和整理阶段可以分别进行,可以有效限制暂停时间。

总结

标记-整理算法适用于老年代,而在年轻代通常采用其他垃圾回收算法,如标记-复制算法或其他更适合的算法。标记-整理算法通常与年轻代的标记-复制算法或其他算法配合使用,以实现整个堆的高效垃圾回收。文章来源地址https://www.toymoban.com/news/detail-709523.html

到了这里,关于Java垃圾收集机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Java虚拟机】JVM垃圾回收机制和常见回收算法原理

    1.垃圾回收机制 (1)什么是垃圾回收机制(Garbage Collection, 简称GC) 指自动管理动态分配的内存空间的机制,自动回收不再使用的内存,以避免内存泄漏和内存溢出的问题 最早是在1960年代提出的,程序员需要手动管理内存的分配和释放 这往往会导致内存泄漏和内存溢出等问

    2024年02月02日
    浏览(38)
  • 深入探讨Java虚拟机(JVM):执行流程、内存管理和垃圾回收机制

    目录 什么是JVM? JVM 执行流程 JVM 运行时数据区 堆(线程共享) Java虚拟机栈(线程私有) 什么是线程私有? 程序计数器(线程私有) 方法区(线程共享) JDK 1.8 元空间的变化 运行时常量池 内存布局中的异常问题 1.  Java堆溢出 2.  虚拟机栈和本地方法栈溢出 JVM 类加载 1.

    2024年02月09日
    浏览(36)
  • 【JVM】JVM垃圾收集器

    垃圾收集器是负责 执行垃圾回收的组件 ,它们用于 管理Java程序运行时的内存分配和释放 。垃圾收集器的主要任务是 自动回收不再使用的内存对象 ,并将 内存空间重新回收 以供程序继续使用。 Serial和Serial Old串行垃圾收集器,是指 使用单线程进行垃圾回收 ,堆内存较小,

    2024年02月13日
    浏览(32)
  • JVM垃圾回收——G1垃圾收集器

    目录 一、什么是G1垃圾收集器 二、G1垃圾收集器的内存划分 三、G1垃圾收集器的收集过程  四、G1收集器的优缺点 五、G1收集器的JVM参数配置         Garbage First(简称G1)收集器是垃圾收集器技术发展史上里程碑式的成果,它摒弃了传统垃圾收集器的严格的内存划分,而是采

    2024年02月05日
    浏览(35)
  • 【JVM】垃圾收集算法

    当前商业虚拟机的垃圾收集器,大多数都遵循了“分代收集”(Generational Collection)[1]的理论进 行设计,分代收集名为理论,实质是一套符合大多数程序运行实际情况的经验法则,它建立在两个分代假说之上: 弱分代假说(Weak Generational Hypothesis):绝大多数对象都是朝生夕

    2024年02月10日
    浏览(34)
  • JVM 垃圾收集器

    重点:CMS,G1,ZGC 主要垃圾收集器如下,图中标出了它们的工作区域、垃圾收集算法,以及配合关系。 Serial 收集器 Serial 收集器是最基础、历史最悠久的收集器。 如同它的名字(串行),它是一个单线程工作的收集器,使用一个处理器或一条收集线程去完成垃圾收集工作。

    2024年02月10日
    浏览(39)
  • jvm垃圾收集算法

    由于《分代收集理论》和不同垃圾收集算法,Java堆应该被划分为不同区域,一般至少会把Java堆划分为 新生代(Young Generation) 和 老年代(Old Generation)两个区域 。 垃圾收集器可以只回收其中某一个或者某些部分的区域对应不同的垃圾回收: “Minor GC”:新生代的垃圾收集

    2024年02月07日
    浏览(32)
  • JVM 垃圾收集

    分代理论 弱分代假说:绝大多数对象都是朝生夕灭,即绝大多数对象都是用完很快需要销毁的。 强分代假说:熬过多次垃圾收集过程的对象就越难以消亡,即如果对象经过多次垃圾收集后仍存活,那么这些对象一般是长久存在难以消亡的,即进入永久代。 跨代引用假说:跨

    2024年02月11日
    浏览(25)
  • JVM垃圾回收算法和CMS垃圾收集器

    目录 判断一个对象是否死亡? 1、引用计数法  2、可达性分析算法 三色标记 垃圾收集算法 1、分代收集理论  2、垃圾回收算法 标记-清除 标记-复制 标记-整理 CMS(Concurrent Mark Sweep)收集器 CMS垃圾收集器步骤 CMS垃圾收集器优缺点 垃圾收集需要完成的三件事情: 哪些内存需

    2024年02月10日
    浏览(35)
  • 08-JVM垃圾收集器详解

    上一篇:07-垃圾收集算法详解 如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。 虽然我们对各个收集器进行比较,但并非为了挑选出一个最好的收集器。因为直到现在为止还没有最好的垃圾收集器出现,更加没有万能的垃圾收集器,我们能做

    2024年02月09日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包