iis服务器助手广告
返回顶部
首页 > 资讯 > 精选 >怎么理解java的垃圾收集器
  • 771
分享到

怎么理解java的垃圾收集器

2023-06-16 12:06:13 771人浏览 薄情痞子
摘要

本篇内容主要讲解“怎么理解java的垃圾收集器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解java的垃圾收集器”吧!初识引用对于刚接触 Java 的 c++ 程序员而言,理解栈和堆的关

本篇内容主要讲解“怎么理解java的垃圾收集器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解java的垃圾收集器”吧!

初识引用

对于刚接触 Java 的 c++ 程序员而言,理解栈和堆的关系可能很不习惯。在 C++ 中,可以使用 new  操作符在堆上创建对象,或者使用自动分配在栈上创建对象。下面的 C++ 语句是合法的,但是 Java 编译器却拒绝这么写代码,会出现 syntax error  编译错误。

Integer foo = Integer(1);

Java 和 C 不一样,Java 中会把对象都放在堆上,需要 new  操作符来创建对象。本地变量存储在栈中,它们持有一个指向堆中对象的引用(指针)。下面是一个 Java 方法,该方法具有一个 Integer 变量,该变量从  String 解析值

public static void foo(String bar){     Integer baz = new Integer(bar); }

这段代码我们使用堆栈分配图可以看一下它们的关系

怎么理解java的垃圾收集器

首先先来看一下 foo() 方法,这一行代码分配了一个新的 Integer 对象,JVM 尝试在堆空间中开辟一块内存空间。如果允许分配的话,就会调用  Integer 的构造方法把 String 字符串转换为 Integer 对象。JVM 将指向该对象的指针存储在变量 baz 中。

上面这种情况是我们乐意看到的情况,毕竟我们不想在编写代码的时候遇到阻碍,但是这种情况是不可能出现的,当堆空间无法为 bar 和 baz  开辟内存空间时,就会出现 OutOfMemoryError,然后就会调用垃圾收集器(garbage collector)  来尝试腾出内存空间。这中间涉及到一个问题,垃圾收集器会回收哪些对象?

垃圾收集器

Java 给你提供了一个 new 操作符来为堆中的对象开辟内存空间,但它没有提供 delete 操作符来释放对象空间。当 foo() 方法返回时,如果变量  baz 超过最大内存,但它所指向的对象仍然还在堆中。如果没有垃圾回收器的话,那么程序就会抛出 OutOfMemoryError 错误。然而 Java  不会,它会提供垃圾收集器来释放不再引用的对象。

当程序尝试创建新对象并且堆中没有足够的空间时,垃圾收集器就开始工作。当收集器访问堆时,请求线程被挂起,试图查找程序不再主动使用的对象,并回收它们的空间。如果垃圾收集器无法释放足够的内存空间,并且JVM  无法扩展堆,则会出现 OutOfMemoryError,你的应用程序通常在这之后崩溃。还有一种情况是 StackOverflowError  ,它出现的原因是因为线程请求的栈深度要大于虚拟机所允许的深度时出现的错误。

标记 - 清除算法

Java 能永久不衰的一个原因就是因为垃圾收集器。许多人认为 JVM  会为每个对象保留一个引用计数,当每次引用对象的时候,引用计数器的值就 + 1,当引用失效的时候,引用计数器的值就 - 1。而垃圾收集器只会回收引用计数器的值为  0 的情况。这其实是 引用计数法(Reference Counting) 的收集方式。但是这种方式无法解决对象之间相互引用的问题,如下

class A{   public B b;  } class B{   public A a; } public class Main{     public static void main(String[] args){     A a = new A();     B b = new B();     a.b=b;     b.a=a;     } }

然而实际上,JVM 使用一种叫做  标记-清除(Mark-Sweep)的算法,标记清除垃圾回收背后的想法很简单:程序无法到达的每个对象都是垃圾,可以进行回收。

标记-清除收集具有如下几个阶段

  • 阶段一:标记

垃圾收集器会从 根(root)  引用开始,标记它到达的所有对象。如果用老师给学生判断卷子来比喻,这就相当于是给试卷上的全部答案判断正确还是错误的过程。

怎么理解java的垃圾收集器

  • 阶段二:清理

在第一阶段中所有可回收的的内容都能够被垃圾收集器进行回收。如果一个对象被判定为是可以回收的对象,那么这个对象就被放在一个 finalization  queue(回收队列)中,并在稍后会由一个虚拟机自动建立的、低优先级的 finalizer 线程去执行它。

怎么理解java的垃圾收集器

  • 阶段三:整理(可选)

一些收集器有第三个步骤,整理。在这个步骤中,GC  将对象移动到垃圾收集器回收完对象后所留下的自由空间中。这么做可以防止堆碎片化,防止大对象在堆中由于堆空间的不连续性而无法分配的情况。

怎么理解java的垃圾收集器

所以上面的过程中就涉及到一个根节点(GC Roots) 来判断是否存在需要回收的对象。这个算法的基本思想就是通过一系列的 GC Roots  作为起始点,从这些节点向下搜索,搜索所走过的路径称为 引用链(Reference Chain),当一个对象到 GC Roots  之间没有任何引用链相连的话,则证明此对象不可用。引用链上的任何一个能够被访问的对象都是强引用 对象,垃圾收集器不会回收强引用对象。

因此,返回到 foo() 方法中,仅在执行方法时,参数 bar 和局部变量 baz  才是强引用。一旦方法执行完成,它们都超过了作用域的时候,它们引用的对象都会进行垃圾回收。

下面来考虑一个例子

LinkedList foo = new LinkedList(); foo.add(new Integer(111));

变量 foo 是一个强引用,它指向一个 LinkedList 对象。LinkedList(jdk.18)  是一个链表数据结构,每一个元素都会指向前驱元素,每个元素都有其后继元素。

怎么理解java的垃圾收集器

当我们调用add() 方法时,我们会增加一个新的链表元素,并且该链表元素指向值为 111 的 Integer 实例。这是一连串的强引用,也就是说,这个  Integer 的实例不符合垃圾收集条件。一旦 foo 对象超出了程序运行的作用域,LinkedList  和其中的引用内容都可以进行收集,收集的

protected void finalize() throws Throwable {     // 清除对象 }

前提是没有强引用关系。

Finalizers

C++  允许对象定义析构函数方法:当对象超出作用范围或被明确删除时,会调用析构函数来清理使用的资源。对于大多数对象来说,析构函数能够释放使用 new 或者 malloc  函数分配的内存。在Java中,垃圾收集器会为你自动清除对象,分配内存,因此不需要显式析构函数即可执行此操作。这也是 Java 和 C++ 的一大区别。

然而,内存并不是唯一需要被释放的资源。考虑  FileOutputStream:当你创建此对象的实例时,它从操作系统分配文件句柄。如果你让流的引用在关闭前超过了其作用范围,该文件句柄会怎么样?实际上,每个流都会有一个  finalizer 方法,这个方法是垃圾回收器在回收之前由 JVM 调用的方法。对于 FileOutputStream 来说,finalizer  方法会关闭流,释放文件句柄给操作系统,然后清除缓冲区,确保数据能够写入磁盘。

任何对象都具有 finalizer 方法,你要做的就是声明 finalize() 方法。如下

protected void finalize() throws Throwable {     // 清除对象 }

虽然 finalizers 的 finalize()  方法是一种好的清除方式,但是这种方法产生的负面影响非常大,你不应该依靠这个方法来做任何垃圾回收工作。因为 finalize  方法的运行开销比较大,不确定性强,无法保证各个对象的调用顺序。finalize 能做的任何事情,可以使用 try-finally  或者其他方式来做,甚至做的更好。

对象的生命周期

综上所述,可以通过下面的流程来对对象的生命周期做一个总结

怎么理解java的垃圾收集器

对象被创建并初始化,对象在运行时被使用,然后离开对象的作用域,对象会变成不可达并会被垃圾收集器回收。图中用红色标明的区域表示对象处于强可达阶段。

JDK1.2 介绍了 java.lang.ref 包,对象的生命周期有四个阶段:?强可达?(Strongly  Reachable?)、软可达(Soft Reachable?)、弱可达(Weak Reachable?)、 幻象可达(Phantom  Reachable?)。

怎么理解java的垃圾收集器

如果只讨论符合垃圾回收条件的对象,那么只有三种:软可达、弱可达和幻象可达。

  • 软可达:软可达就是?我们只能通过软引用?才能访问的状态,软可达的对象是由 SoftReference  引用的对象,并且没有强引用的对象。软引用是用来描述一些还有用但是非必须的对象。垃圾收集器会尽可能长时间的保留软引用的对象,但是会在发生  OutOfMemoryError 之前,回收软引用的对象。如果回收完软引用的对象,内存还是不够分配的话,就会直接抛出 OutOfMemoryError。

  • 弱可达:弱可达的对象是 WeakReference 引用的对象。垃圾收集器可以随时收集弱引用的对象,不会尝试保留软引用的对象。

  • 幻象可达:幻象可达是由 PhantomReference 引用的对象,幻象可达就是没有强、软、弱引用进行关联,并且已经被 finalize  过了,只有幻象引用指向这个对象的时候。

除此之外,还有强可达和不可达的两种可达性判断条件

  • 强可达:就是一个对象刚被创建、初始化、使用中的对象都是处于强可达的状态

  • 不可达(unreachable):处于不可达的对象就意味着对象可以被清除了。

下面是一个不同可达性状态的转换图

怎么理解java的垃圾收集器

判断可达性条件,也是 JVM 垃圾收集器决定如何处理对象的一部分考虑因素。

所有的对象可达性引用都是 java.lang.ref.Reference 的子类,它里面有一个get()  方法,返回引用对象。如果已通过程序或垃圾收集器清除了此引用对象,则此方法返回 null  。也就是说,除了幻象引用外,软引用和弱引用都是可以得到对象的。而且这些对象可以人为拯救,变为强引用,例如把 this  关键字赋值给对象,只要重新和引用链上的任意一个对象建立关联即可。

ReferenceQueue

引用队列又称为 ReferenceQueue,它位于 java.lang.ref  包下。我们在?建各种引用(软引用,弱引用,幻象引用)并关联到响应对象?时,可以选择是否需要关联引用队列。JVM  会在特定的时机将引用入队到队列中,程序可以通过判断引用队列中是否已经加入引用,来了解被引用的对象是否被GC回收。

Reference

java.lang.ref.Reference 为软(soft)引用、弱(weak)引用、虚(phantom)引用的父类。因为  Reference 对象和垃圾回收密切配合实现,该类可能不能被直接子类化。

到此,相信大家对“怎么理解java的垃圾收集器”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: 怎么理解java的垃圾收集器

本文链接: https://www.lsjlt.com/news/283708.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么理解java的垃圾收集器
    本篇内容主要讲解“怎么理解java的垃圾收集器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解java的垃圾收集器”吧!初识引用对于刚接触 Java 的 C++ 程序员而言,理解栈和堆的关...
    99+
    2023-06-16
  • Java的垃圾回收怎么理解
    这篇“Java的垃圾回收怎么理解”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java的垃圾回收怎么理解”文章吧。在说记忆集...
    99+
    2023-06-29
  • JVM垃圾回收——G1垃圾收集器
    目录 一、什么是G1垃圾收集器 二、G1垃圾收集器的内存划分 三、G1垃圾收集器的收集过程  四、G1收集器的优缺点 五、G1收集器的JVM参数配置 一、什么是G1垃圾收集器         Garbage First(简称G1)收集...
    99+
    2023-10-25
    jvm java G1
  • 垃圾收集趣史-Java垃圾收集算法 --- 王咏刚
    在了解垃圾收集算法的起源之前,有必要先回顾一下内存分配的主要方式。我们知道,大多数主流的语言或运行环境都支持三种最基本的内存分配方式,它们分别是: ...
    99+
    2023-06-03
  • 怎么理解Java 垃圾回收机制
    怎么理解Java 垃圾回收机制,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。什么是自动垃圾回收自动垃圾回收是一种在堆内存中找出哪些对象在被使用,还有哪些对象没被使用,并且将...
    99+
    2023-06-05
  • Java垃圾回收机制怎么理解
    这篇文章主要讲解了“Java垃圾回收机制怎么理解”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java垃圾回收机制怎么理解”吧!Java垃圾回收是一个自动运行的管理程序运行时使用的内存的进程...
    99+
    2023-06-17
  • Java中如何使用垃圾收集器
    Java中如何使用垃圾收集器,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Java垃圾收集器使用小诀窍,垃圾收集器(Garbage Collector,GC)是现代软件虚拟机技...
    99+
    2023-06-17
  • JVMGC垃圾收集梳理总结
    目录什么是垃圾?什么是GC?如何发现垃圾?垃圾如何处理?常见的垃圾收集算法标记清除(mark sweep)拷贝算法 (copying)标记压缩/标记整理(mark compact)J...
    99+
    2024-04-02
  • 详解Java 虚拟机(第⑤篇)——垃圾收集
    垃圾收集主要是针对堆和方法区进行。程序计数器、虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后就会消失,因此不需要对这三个区域进行垃圾回收。一、判断一个对象是否可被回收1. 引用计数算法为对象添加一个引用...
    99+
    2023-06-05
  • 如何理解Java垃圾回收
    这篇文章主要介绍“如何理解Java垃圾回收”,在日常操作中,相信很多人在如何理解Java垃圾回收问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何理解Java垃圾回收”的疑惑有所帮助!接下来,请跟着小编一起来...
    99+
    2023-06-15
  • 深入理解Java虚拟机之经典垃圾收集器
    目录1. 综述1. 总述:2. 图示总述3. 应用中应如何做出选择?2. Serial收集器1. 简介2. 图解工作过程3.使用的垃圾收集算法4. 优点5. 缺点6. 主要应用场景3...
    99+
    2024-04-02
  • java垃圾收集器有哪些及怎么使用
    这篇文章主要介绍“java垃圾收集器有哪些及怎么使用”,在日常操作中,相信很多人在java垃圾收集器有哪些及怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java垃圾收集器有哪些及怎么使用”的疑惑有所...
    99+
    2023-07-02
  • java 垃圾回收机制以及经典垃圾回收器详解
    判断对象存活方法 引用计数法:在对象中添加一个引用计数子,每当一个地方引用他时,计数器就加一,当引用失效时,计数器就减一。 会有对象循环引用问题: objA.instance =...
    99+
    2024-04-02
  • java中GC算法和垃圾收集器怎么使用
    在Java中,GC(垃圾回收)算法和垃圾收集器是自动管理内存的关键组件。以下是关于如何使用GC算法和垃圾收集器的一些基本指南:1. ...
    99+
    2023-08-24
    java
  • 怎么理解JVM1.4.1版本中的JVM垃圾收集策略
    本篇文章给大家分享的是有关怎么理解JVM1.4.1版本中的JVM垃圾收集策略,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。我们分析了引用计数、复制、标记-清除和标记-整理这些经...
    99+
    2023-06-17
  • 怎么理解Python中的垃圾回收
    这篇文章主要介绍“怎么理解Python中的垃圾回收”,在日常操作中,相信很多人在怎么理解Python中的垃圾回收问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解Python中的垃圾回收”的疑惑有所帮助!...
    99+
    2023-06-16
  • Java jvm垃圾回收详解
    目录常见面试题1.JVM内存回收和分配1.1主要的区域?gc测试1.2大对象进入老年代1.3长期存活的对象进入老年代1.4主要进行gc的区域gc的类型Young GcFull Gc1...
    99+
    2024-04-02
  • JVM常用垃圾收集器详细解说
    目录前言新生代垃圾收集器老年代垃圾收集器不分代垃圾收集器前言 在上一篇,我们谈到了jvm垃圾回收算法详细解析,并了解了JVM中针对堆区中不同的分代采用不同的垃圾回收算法 在了解了垃圾...
    99+
    2024-04-02
  • java垃圾收集器与内存分配策略详解
    目录1.经典垃圾收集器1.1 Serial收集器1.2 ParNew收集器1.3 Parallel Scavenge 收集器1.4 Serial Old 收集器1.5 Paralle...
    99+
    2024-04-02
  • 怎么理解JavaScript垃圾回收机制
    本篇内容介绍了“怎么理解JavaScript垃圾回收机制”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!机制说明找出不再使用的变量,然后释放它...
    99+
    2023-06-25
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作