JVM 垃圾回收

在 JVM 调优中一个离不开的重点是垃圾回收,当垃圾回收成为系统达到更高并发量的瓶颈时,我们就需要对 JVM 中 “自动化” 垃圾回收技术实施必要的监控和调节。

对于调优之前,我们必须要了解其运行原理,java 的垃圾收集 Garbage Collection 通常被称为 “GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了。因此本篇主要从这三个方面来了解:

  1. 哪些对象需要被回收?

  2. 什么时候回收?

  3. 如何回收?

谁要被回收?

java 虚拟机在执行 java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域,这些区域有各自各自的用途。主要包含以下几个部分组成:

程序计数器

程序计数器占用的内存空间我们可以忽略不计,它是每个线程所执行的字节码的行号指示器。

虚拟机栈

java 的虚拟机栈是线程私有的,生命周期和线程相同。它描述的是方法执行的内存模型。同时用于存储局部变量、操作数栈、动态链接、方法出口等。

本地方法栈

本地方法栈,类似虚拟机栈,它调用的是 native 方法。

堆是 JVM 中管理内存中最大一块。它是被共享,存放对象实例。也被称为 “GC堆”,是垃圾回收的主要管理区域。

方法区

方法区也是共享的内存区域。它主要存储已被虚拟机加载的类信息、常量、静态变量、即时编译器(jit)编译后的代码数据。

以上就是 JVM 在运行时期主要的内存组成,我们看到常见的内存使用不但存在于堆中,还会存在于其他区域,虽然堆的管理对程序的管理至关重要,但我们不能只局限于这一个区域,特别是当出现内存泄露的时候,我们除了要排查堆内存的情况,还得考虑虚拟机栈的以及方法区域的情况。

知道了要对谁以及那些区域进行内存管理,还需要知道什么时候对这些区域进行垃圾回收。

什么时候回收?

在垃圾回收之前,我们必须确定的一件事就是对象是否存活?这就牵扯到了判断对象是否存活的算法了。

引用计数算法

给对象中添加一个引用计数器,每当有一个地方引用它时,计数器 +1,当引用失效,计数器 -1。任何时刻计数器为0的对象就是不可能再被使用的。

  • 优点:实现简单,判定效率高效,被 actionscript3 和 python 中广泛应用。

  • 缺点:无法解决对象之间的相互引用问题,Java 没有采纳。

可达性分析算法

通过一系列称为 “GC Roots” 的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到 GCRoots
没有任何引用链相连的时候,则证明此对象是不可用的。

比如下图,右侧的对象是到 GCRoot 时不可达的,可以判定为可回收对象。

在 java 中,可以作为 GCRoot 的对象包括以下几种:

  • 虚拟机栈中引用的对象。

  • 方法区中静态属性引用的对象。

  • 方法区中常量引用的对象。

  • 本地方法中 JNI 引用的对象。

基于以上,我们可以知道,当当前对象到 GCRoot 中不可达时候,即会满足被垃圾回收的可能。

那么是不是这些对象就非死不可,也不一定,此时只能宣判它们存在于一种“缓刑”的阶段,要真正的宣告一个对象死亡。至少要经历两次标记:

第一次:对象可达性分析之后,发现没有与 GCRoots 相连接,此时会被第一次标记并筛选。

第二次:对象没有覆盖 finalize() 方法,或者 finalize() 方法已经被虚拟机调用过,此时会被认定为没必要执行。

如何回收?

上述的两点讲解之后,我们大概明白了,哪些对象会被回收,以及回收的依据是什么,但回收的这个工作实现起来并不简单。

首先它需要扫描所有的对象,鉴别谁能够被回收,其次在扫描期间需要 “stop the world”,对象会被冻结,不然你刚扫描,引用信息有变化,就等于白做了。

分代回收

我们从一个 object1 来说明其在分代垃圾回收算法中的回收轨迹。

1、object1新建,出生于新生代的 Edan 区域。

2、minor GC,object1 还存活,移动到 Fromsuvivor 空间,此时还在新生代。

3、minor GC,object1 仍然存活,此时会通过复制算法,将 object1 移动到 ToSuv 区域,此时 object1 的年龄 age+1。

4、minor GC,object1 仍然存活,此时 survivor 中和 object1 同龄的对象并没有达到 survivor 的一半,所以此时通过复制算法,将 fromSuv 和 Tosuv 区域进行互换,存活的对象被移动到了Tosuv。

5、minor GC,object1 仍然存活,此时 survivor 中和 object1 同龄的对象已经达到 survivor 的一半以上(toSuv 的区域已经满了),object1 被移动到了老年代区域。

6、object1 存活一段时间后,发现此时 object1 不可达 GcRoots,而且此时老年代空间比率已经超过了阈值,触发了 majorGC(也可以认为是 fullGC,但具体需要垃圾收集器来联系),此时 object1 被回收了。fullGC 会触发 stop the world。

在以上的新生代中,我们有提到对象的 age,对象存活于 survivor 状态下,不会立即晋升为老生代对象,以避免给老生代造成过大的影响,它们必须要满足以下条件才可以晋升:

1、minor gc 之后,存活于 survivor 区域的对象的 age 会 +1,当超过(默认)15 的时候,转移到老年代。

2、动态对象,如果 survivor 空间中相同年龄所有的对象大小的综合和大于 survivor 空间的一半,年纪大于或等于该年纪的对象就可以直接进入老年代。

以上采用分代垃圾收集的思想,对一个对象从存活到死亡所经历的历程。期间,在新生代的时刻,会用到复制算法,在老年代时,有可能会用到标记 - 清除算法(mark-sweep)算法或者标记 - 整理算法,这些都是垃圾回收算法基于不同区域的实现,我们看下这几种回收算法的实现原理。

垃圾回收算法

标记清除法(Mark-Sweep)

标记清除法是垃圾回收算法的思想基础。标记清除算法将垃圾分为两个阶段:标记阶段和清除阶段。

标记阶段,通过根节点,标记所有从根节点开始的可达对象,未标记过的对象就是未被引用的垃圾对象。

清除阶段,清除所有未被标记的对象。

复制算法(Copying)

复制算法是,将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中存活对象复制到未使用的内存块,然后清除使用的内存块中所有的对象。

标记压缩算法(Mark-Compact)

标记压缩算法是一种老年代的回收算法。

标记阶段和标记清除算法一致,对可达对象做一次标记。

清理阶段,为了避免内存碎片产生,将所有的存活对象压缩到内存的一端。

垃圾收集器

垃圾收集器是内存回收的具体实现,不同的厂商提供的垃圾收集器有很大的差别,一般的垃圾收集器都会作用于不同的分代,需要搭配使用。以下是各种垃圾收集器的组合方式:

各种组合的优缺点:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容