什么是垃圾回收?

从字面看来,按字面意思来理解就是--找到垃圾对象并将他们抛弃掉;事实却正好相反,垃圾回收是把处于活动状态的对象找出来,而将剩余的对象标记为垃圾对象。基于此理论,我们来详细描述java virtual machine的自动垃圾回收机制。

我们首先从最基础的垃圾回收的一些属性、概念、方法讲起,而不会直奔主题:JVM的垃圾回收机制。

声明:  这边文章主要论述Oracle HotSpot和OpenJDK的垃圾回收机制。至于其它的一些JVM,例如JRockit或者IBM J9,它们可能采用了不同机制来实现垃圾回收。

手动管理内存(Mannual memory management)

在介绍现在流行的自动垃圾回收机制之前,先让我们回到手动为数据分配内存,然后再手动回收这些内存的时代吧。在那个年代,如果你忘记了释放这些已分配的内存,那么就不能再重新使用这些内存空间了。内存虽然已经被声明进行了分配,但是确不能再使用,我们管这样的场景就叫:内存泄漏

下面是一段用C语言开发的手动管理内存的代买:

int send_request() {size_t n = read_size();int *elements = malloc(n * sizeof(int));if(read_elements(n, elements) < n) {// elements not freed!return -1;}// …free(elements)return 0;
}

从代码当中我们可以看出,很容易忘记去释放内存,从而发生内存泄漏问题。发生内存泄漏以后,我们只能通过排查代码的方式找到具体的原因。所以,最好的方式就是有一种机制,自动的去回收不再使用的内存,从而降低人为错误的概率。这种自动回收内存的机制就叫Garbage Collection(简称:GC)。

智能指针

实现自动化垃圾回收的最直接的一种方式就是利用destructor。例如,我们可以利用C++里得vector来实现,当变量从vector脱离以后,destructor就会自动被调用,从而回收内存:

int send_request() {size_t n = read_size();vector<int> elements = vector<int>(n);if(read_elements(elements.size(), &elements[0]) < n) {return -1;}return 0;
}

但是在一些复杂的场景中,特别是共享对象被多线程同时引用的时候,单单利用destructor明显不能满足需求。基于以上的场景,最简单的方式就是:对对象的被引用进行计数。针对每个对象,我们会记录下这个对象当下被引用的次数是多少,当被引用的次数变为0的时候,表明这个对象占用的内存就可以被回收了。很著名的一个实现就是利用C++的共享指针了:

int send_request() {size_t n = read_size();auto elements = make_shared<vector<int>>();// read elementsstore_in_cache(elements);// process elements furtherreturn 0;
}

为了避免函数在被调用的时候,元素再一次被读取,我们可以将其放进缓存,在这种场景下,利用vector来进行对象销毁就不可行了。因此,我们改为利用shared_ptr,它将持续关注元素的被引用数,当指针在其它地方被引用的时候,引用数就会加一,当指针被释放的时候,引用数就会减一,当引用数被减为0时,shared_ptr就是删除所关联的vector。

自动化内存管理(Automated memory management)

观察上面的C++代码,我们可以明确什么时候需要关心内存的管理。但是,我们如果将这种机制应用到所有的对象上面将会怎么样?这将使得我们的工作变得非常顺手,因为,作为开发者,再也不用关心垃内存回收的问题了。在运行的过程当中,将自动检测出不再被使用的对象,并清除它们以便释放内存空间。换句话说,就是自动进行垃圾回收。第一个垃圾回收器是LISP语言的,诞生于1959年,以后的日子了,这项技术在不断的进步。

引用计数法(reference counting)

很多的语言,例如Perl、PHP、Python都是采用我们上文提到的C++共享指针的方式进行垃圾回收。通过下图可能展示的更清晰:

绿色的云区域表示被他们所引用到的对象还在被程序所使用,这些对象可能是当前运行方法里的本地变量,也可能为一些静态变量,或者其它的一些对象。每种语言与每种语言在这方面可能会有不同,但这些不是重点。

蓝色的链路代表内存中的活跃对象调用链路,圆圈的数字标识了这个对象当前被引用的次数。灰色的链条代表了那些没有再被显示引用到的对象(指得是那些被绿色的云引用到的对象)。灰色的对象就是可以被垃圾回收器回收的垃圾对象了。

这个方法看起来真的很好,但是却有一个致命的缺陷,就是会产生分离的垃圾闭环,上面的对象实际上已经没有意义了,但是它们的被引用数又都不为零。如下图所示:

图中的红色闭环,实际上已经成为了应用程序不再使用的垃圾对象,但是由于被引用数不为零,所以不能被回收,从而造成了内存泄漏的问题。

有很多的办法可以解决这个问题,例如可以利用弱引用的方式(‘weak’reference),也可以采用单独的算法对闭环链路进行垃圾回收。 我们上文提到的Perl、Python、PHP都会采用其中的一种方式来进行垃圾回收。 我们将不会对它们的实现进行详细描述,而是在后续的章节当中,对JVM的机制进行详细解读。

标记清除(Mark and Sweep)

在如何遍历活跃对象的方法上JVM比较特别,不像上节似的定义的绿色的云是模糊不清的,JVM明确的定义了几组叫做Garbage Collection Roots的对象:

  • Local variables
  • Active threads
  • Static fields
  • JNI references

我们将JVM对所有活跃对象进行追踪标记,而将未标记的对象进行内存回收再分派的过程叫做Mark and Sweep算法,主要由两步来完成。

Mark阶段,从GC roots对象开始对可到达的对象进行一次遍历标记,并对所有这些对象,在本地内存中做一个分类。

Sweep阶段,将那些没有被遍历到的对象占用的内存空间进行回收,以便在下次的内存分派过程重新使用。

JMV有很多种的垃圾回收算法,比如说Parallel ScavengeParallel Mark+Copy 或者CMS,他们基本上都是按照上述方式实现的,细节可能会有不同,但是核心思想都是按照上述的两步来进行实现的。

这种方式一个重要的优点就是避免了因垃圾闭环而导致的内存泄漏问题:

而缺点就是,当进行垃圾回收的时候,所有的应用线程都要进行一下暂停。因为如果程序不暂停,就没有办法准确的计算出每个对象的被引用数是多少。我们把这种为了能够准确的找出活跃对象,而让程序临时暂停的方式叫做:Stop the word pause,这种暂停的发生可能有很多的原因,但其中最重要的就是为了进行垃圾回收。

细说JVM的垃圾回收机制相关推荐

  1. jvm垃圾回收机制_深入理解JVM的垃圾回收机制

    ​如何判断对象已"死" Java堆中存放着几乎所有的对象实例,垃圾回收器在堆进行垃圾回收前,首先要判断这些对象那些还存活,那些已经"死去".判断对象是否已&qu ...

  2. Java虚拟机(三)——初识JVM的垃圾回收机制

    前言 对于程序计数器.虚拟机栈.本地方法栈这三个部分而言,其生命周期与相关线程有关,随线程而生,随线程而灭.并且这三个区域的内存分配与回收具有确定性,因为当方法结束或者线程结束时,内存就自然跟着线程回 ...

  3. JVM的垃圾回收机制详解和调优

    1.JVM的gc概述 gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存.java语言并不要求jvm有gc,也没有规定gc如何工作.不过常用的jvm都有gc,而且大多数gc都使用类似的 ...

  4. jvm gc垃圾回收机制和参数说明amp;amp;Java JVM 垃圾回收(GC 在什么时候,对什么东西,做了什么事情)

    jvm gc(垃圾回收机制) Java JVM  垃圾回收(GC 在什么时候,对什么东西,做了什么事情) 前言:(先大概了解一下整个过程) 作者:知乎用户 链接:https://www.zhihu.c ...

  5. 【JVM】垃圾回收机制及算法

    垃圾回收机制及算法 一.垃圾回收概述 二.对象是否存活 1. 判断对象是否存活 - 引用计数算法 2.判断对象是否存活-可达性分析算法 1.可达性分析算法 2.JVM之判断对象是否存活 3.关于引用 ...

  6. 深入理解JVM(四)JVM的垃圾回收机制

    文章目录 1 什么是垃圾回收机制 2 Java中的引用类型 3 如何判断对象是否可以被回收 4 方法区的垃圾收集 5 垃圾收集算法 5.1 标记-清除(Mark-Sweep)算法 5.2 标记整理(M ...

  7. JVM原理-垃圾回收机制及算法

    JVM原理-jvm内存模型 jvm内存模型 一.垃圾回收机制算法 1. 判断对象是否回收算法 垃圾收集器在做垃圾回收的时候,首先需要判定的就是哪些内存是需要被回收的,哪些对象是存活的,是不可以被回收的 ...

  8. JVM之垃圾回收机制

    垃圾回收机制 垃圾回收时机 System.gc() JVM垃圾回收机制决定 垃圾回收策略---如何判断对象已死? 引用计数算法 可达性分析算法 需要垃圾回收的内存 方法区/元空间 堆 新生代(Youn ...

  9. 浅谈Java虚拟机JVM的垃圾回收机制

    1. 什么是垃圾 要回收垃圾,那么垃圾是什么?简单的逻辑就是不会再被使用的内存对象呗. 2. 怎么判断不再被使用 2.1 引用计数法.统计有多少个引用指向内存对象,如果没有引用指向内存对象,那么该内存 ...

最新文章

  1. c语言中getc与gets,getc()和gets()的用法
  2. Golang库学习笔记 Gin(一)
  3. Python(4)--Pycharm安装、使用小技巧
  4. html自动适应屏幕分辨率,css如何自适应屏幕大小?
  5. String,StringBuilder, StringBuffer
  6. 是时候了解React Native了
  7. 最低什么样的学历,才可以选择转行web前端?
  8. matlab size11,matlab学习笔记11_3高维数组操作 filp, shiftdim, size, permute, ipermute
  9. 流体力学CFD前处理软件-Gambit
  10. 人脸识别数据集的建立(dlib+opencv)及人脸识别
  11. Vue加载组件、动态加载组件的几种方式
  12. 记一次hive 报错NoViableAltException(-1@[215:51: ( KW_AS )?])
  13. 以《西游记》为例 详解游戏设计归纳演绎法
  14. 74hc595级联c语言程序,stm32使用三片74HC595级联程序代码
  15. 正确去掉Win7快捷方式小箭头
  16. ICCV 2015 B-CNN细粒度分类
  17. 前端学习--Bable的使用步骤
  18. html弹窗后 自动关闭页面,网页一键复制弹出提示窗口后几秒后自动关闭提示js代码...
  19. 成为IT精英,我奋斗了7年
  20. Oracle魔改linux,linux shell脚本攻略 第3版 pdfssr 魔改v3一键

热门文章

  1. 光固化3D打印 二 LCD技术
  2. LED透明屏什么牌子好?2021年LED透明屏品牌排行榜
  3. iptables之ipset使用介绍
  4. 用pandas批量处理Excel中的空值与批量合并Excel
  5. 汲取ing《凤凰男与凤凰女》转自Baidu.
  6. Storm上游数据源之Kakfa
  7. 董超团队提出VapSR:基于超大感受野注意力的超分辨率模型
  8. 常用linux编辑器使用(备查)
  9. YOLOv5的Tricks | 【Trick15】使用COCO API评估模型在自己数据集的结果
  10. Python爬取代理池并清洗可用IP