Java垃圾回收机制

话题:简单描述下jvm的垃圾回收策略,比如引用计数、标记清除等策略

从Java堆内存说起

堆是在JVm启动时候创建的,主要是维护运行时数据,如运行过程中创建的对象和数组都是基于这块内存空间。Java堆内存是非常重要的元素,如果我们动态创建的对象没有及时回收,持续堆积,最后会导致堆空间被占满,内存溢出。

因此,Java提供看一种垃圾回收机制,在后台创建一个收获线程。该线程在内存紧张的时候自动跳出来,把堆内存全部进行回收,从而保证程序的正常运行。

什么是垃圾

所谓“垃圾”,是指不再存活的对象们。常见的判断方法有2种:引用计数法和可达性分析

引用计数法

为每一个创建的对象分配一个引用计数器,用来存储该对象被引用的次数。次数为零,表示没有人在使用这个对象,可以认为“对象死亡”。但是,这种方案存在严重的问题,就是无法检测“循环引用”:当两个对象相互引用,即使他们不被外界任何东西引用,他们的计数都不为零,因此永远不会被回收。而实际上对于开发者而言,这两个对象已经完全没有用处。

可达性分析

基本思路是把所有引用的对象看成一棵树,从树的根节点出发,持续遍历查找所有连接的树枝对象,这些对象被称作可达对象或存活对象。其余的对象则被称为不可达对象或垃圾。

回收策略

1 、标记-清理

第一步,利用可达性遍历堆内存,把存活对象和“垃圾”进行标记。

第二步,再遍历一遍,把所有“垃圾”所占用的空间直接清空。

特点:简单方便,容易产生内存碎片

2 、标记-整理

在清理的时候,把所有存活对象扎堆到同个地方,让他们待在一起,这样就没有内存碎片。

这两种方案适合 存活对象多,垃圾少的情况,他只需要清理掉少量的垃圾,然后挪动下存活的对象即可。

3、复制

这种方案比较粗暴,直接把堆内存分成两部分,一段时间内只允许在其中一块内存上进行分配,当这块内存被分配完后,则进行垃圾回收,把所有存活的对象全部复制到另外一块内存上,当前内存则全部清空。

这种方案适合存活对象少,垃圾多的情况。这样在复制的时候就不需要复制多少对象过去,多数垃圾直接被清空处理。

Java的分代回收机制

Java是如何选择这三种回收算法呢?

Java的堆结构

一块Java堆空间一般分为三部分,这三部分可以用来存储三类数据:

  • 刚刚创建的对象。在代码运行时候会不断地创建新的对象,这些对象会被统一放在一起。因为有很多局部变量在新创建后很快就会变成不可达的对象,快速死去,因此这块区域的特点是存活对象少,垃圾多。形容这块区域为:新生代;
  • 存活了一段时间的对象。这些对象早早就被创建了,而且一直存活下来, 我们把这些存活时间比较长的对象放在一起,他们的特点是存活对象多,垃圾少。形容这块区域为:老年代;
  • 永久存活的对象。比如一些静态文件,这些对象的特点是不需要垃圾回收,永远存活。形容这块区域为永久代。

结合新生代/老年代的存活特点和之前学习的几种垃圾回收算法,可以得到如下的回收方案:

新生代-复制回收机制

对于新生代区域,由于每次 GC 都会有大量新对象死去,只有少量存活。因此采用 复制 回收算法,GC 时把少量的存活对象复制过去即可。

那么如何设计这个 复制 算法比较好呢?有以下几种方式:

思路 1. 把内存均分成 1:1 两等份

每次只使用一半的内存,当这一半满了后,就进行垃圾回收,把存活的对象直接复制到另一半内存,并清空当前一半的内存。

这种分法的缺陷是相当于只有一半的可用内存,对于新生代而言,新对象持续不断地被创建,如果只有一半可用内存,那显然要持续不断地进行垃圾回收工作,反而影响到了正常程序的运行,得不偿失。

思路 2. 把内存按 9:1 分

既然上面的分法导致可用内存只剩一半,那么我做些调整,把 1:1变成9:1,

最开始在 9 的内存区使用,当 9 快要满时,执行复制回收,把 9 内仍然存活的对象复制到 1 区,并清空 9 区。

这样看起来是比上面的方法好了,但是它存在比较严重的问题。

当我们把 9 区存活对象复制到 1 区时,由于内存空间比例相差比较大,所以很有可能 1 区放不满,此时就不得不把对象移到 老年区 。而这就意味着,可能会有一部分 并不老 的 9 区对象由于 1 区放不下了而被放到了 老年区 ,可想而知,这破坏了 老年区 的规则。或者说,一定程度上的老年区 并不一定全是 老年对象。

那应该如何才能把真正比较老的对象挪到老年区 呢?

思路 3. 把内存按 8:1:1 分

既然 9:1 有可能把年轻对象放到老年区 ,那就换成 8:1:1,依次取名为 Eden、Survivor A、Survivor B 区,其中Eden 意为伊甸园,形容有很多新生对象在里面创建;Survivor区则为幸存者,即经历 GC 后仍然存活下来的对象。

工作原理如下:

  • 首先,Eden区最大,对外提供堆内存。当 Eden区快要满了,则进行 Minor GC,把存活对象放入 Survivor A 区,清空 Eden 区;

  • Eden区被清空后,继续对外提供堆内存;

  • 当 Eden 区再次被填满,此时对 Eden 区和 Survivor A 区同时进行 Minor GC,把存活对象放入 Survivor B 区,同时清空 Eden 区和Survivor A 区;

  • Eden区继续对外提供堆内存,并重复上述过程,即在 Eden 区填满后,把 Eden 区和某个 Survivor 区的存活对象放到另一个 Survivor 区;

  • 当某个 Survivor 区被填满,且仍有对象未被复制完毕时,或者某些对象在反复 Survive15 次左右时,则把这部分剩余对象放到Old 区;

  • 当 Old 区也被填满时,进行 Major GC,对 Old 区进行垃圾回收。
    [注意,在真实的 JVM 环境里,可以通过参数 SurvivorRatio 手动配置 Eden 区和单个 Survivor 区的比例,默认为 8。]

那么,所谓的 Old 区垃圾回收,或称Major GC,应该如何执行呢?

老年代-标记整理回收机制

根据上面我们知道,老年代一般存放的是存活时间较久的对象,所以每一次 GC 时,存活对象比较较大,也就是说每次只有少部分对象被回收。

因此,根据不同回收机制的特点,这里选择 存活对象多,垃圾少的标记整理 回收机制,仅仅通过少量地移动对象就能清理垃圾,而且不存在内存碎片化。

至此,我们已经了解了Java堆内存的分代原理,并了解了不同代根据各自特点采用了不同的回收机制,即新生代采用复制回收机制,老年代采用标记整理 机制。

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

推荐阅读更多精彩内容

  • 如果你想要从太空观察地球,卫星技术就能够做到这一点。图中的海洋流是卫星地图展现的,紫色和粉红色的漩涡代表更暖的洋流...
    allever阅读 1,397评论 0 8
  • 来自: Android梦想特工队作者: Aaron主页: http://www.wxtlife.com/原...
    技术特工队阅读 4,371评论 0 28
  • 一、常用垃圾回收机制 1. 标记-清除算法(mark-sweep) 顾名思义,标记-清除算法分为两个阶段,标记(m...
    molscar阅读 308评论 0 0
  • JVM本身是硬件的一层软件抽象,在这之上才能够运行Java程序,也才有了我们所吹嘘的平台独立性以及“一次编写,处处...
    洋芋掉到碗里去了阅读 835评论 0 6
  • 一:垃圾回收机制的意义 java 语言中一个显著的特点就是引入了java回收机制,是c++程序员最头疼的内存管理...
    FTOLsXD阅读 511评论 0 2