GC浅谈(一)

人所缺乏的不是才干而是志向,不是成功的能力而是勤劳的意志。-部尔卫

Java语言的一大特点就是可以进行自动垃圾回收处理,而无需开发人员过于关注系统资源的释放,大大减轻了开发人员的工作量,但同时也增加了软件系统的负担。
  垃圾收集器要解决的问题是:

  • 哪些对象需要回收
  • 何时回收这些对象
  • 如何回收这些对象

1. 判断对象可被回收的几种算法

在JVM堆内存中存放着JAVA程序几乎所有的对象实例,垃圾收集器在对堆内存进行回收前,首先要确定的是哪些对象是需要被回收的。

1.1 引用计数算法

引用计数法是最经典也是最古老的一种垃圾收集方法。
  引用计数器的实现很简单,对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器加1,当不再引用时,则减1.若对象A的引用计数器的值为0,则对象可被回收。
  该方法存在一个问题,无法处理循环引用的情况。如对象A和对象B,对象A中存在对象B的引用,对象B中存在对象A的引用,两个对象的引用计数器都不为0,但却不存在第三个对象引用了A或B。这种情况下,对象A和B是应该被回收的,但由于引用计数器不为0.垃圾收集器却不能将内存回收,引起内存泄漏。
  由于无法处理循环引用的问题,引用计数法不适用于JVM的垃圾回收。

1.2 可达性分析算法

这个算法就是通过"GC Roots"的对象作为起始点,从这些点向下搜索,搜索走过的路径称为引用链,若某个对象到GC Roots没有任何引用链时,则该对象时不可用的,将会被判断为可回收的对象。如下图所示:

判断对象是否可被回收

可作为GC Roots的对象包含下面几种:
  (1) 虚拟机栈(栈帧中的本地变量表)中引用的对象
  (2) 方法区中类静态属性引用的对象
  (3) 方法区中常量引用的对象
  (4) 本地方法栈(即native)引用的对象

2. 垃圾收集算法

2.1 标记-清除算法

标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。标记-清除算法先通过根节点(GC Roots)标记所有可达对象,然后清除所有未被标记的对象,完成垃圾回收。标记-清除算法可能产生最大的问题就是空间碎片(即内存空间不连续)。如下图所示:

标记-清除算法

2.2 复制算法

复制算法的核心思想是:将内存空间分为两块,每次只使用其中的一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,再清除正在使用的内存中的所有对象。该算法可确定回收后的内存空间没有碎片,但是缺点是系统内存折半。如下图所示:

复制算法

在JVM的新生代串行收集器中,使用了复制算法。新生代分为eden、from、to三个部分。其中from和to是用于复制的两块大小相同的内存块,用于存放未被回收的对象。

适用复制算法的前提是存活对象少,垃圾对象多的内存空间。

2.3 标记-压缩算法

标记-压缩算法是老年代的回收算法,分为标记和压缩两个阶段。标记阶段从根节点开始,对所有可达对象做一次标记,压缩阶段是将所有存活对象压缩到内存的一端,然后清理边界所有的空间。这种方法同样也避免产生空间碎片。如下图所示:

标记-压缩

2.4 增量算法

对于大部分垃圾回收算法而言,在垃圾回收过程中,程序将处于一种Stop the world的状态。在Stop the world状态下,程序所有的线程将被挂起,等待垃圾回收的完成。如果垃圾回收时间过长,应用程序将会被挂起很久。
  增量算法的思想是:让垃圾收集线程和应用程序线程交替执行。垃圾收集线程只收集一小片区域的内存空间,接着切换到应用程序线程,以此反复,直至垃圾回收完成。使用这种方式,能减少系统的停顿时间,但是,因为线程切换和上下文转换的消耗,使得垃圾回收成本上升,造成系统吞吐量下降。

2.5 分代算法

分代算法的思想是:根据内存空间的特点,使用合适的回收算法,以提高垃圾回收的效率。
  以HotSpot为例,新生代因为存活对象少,垃圾对象多,使用复制算法,效率会很高。老年代存活对象多,垃圾对象少,因此适用标记-压缩算法,以提高回收效率。

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

推荐阅读更多精彩内容

  • 1.什么是垃圾回收? 垃圾回收(Garbage Collection)是Java虚拟机(JVM)垃圾回收器提供...
    简欲明心阅读 89,366评论 17 311
  • 一. 垃圾回收的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对...
    Stan_Z阅读 1,918评论 0 25
  • 原文阅读 前言 这段时间懈怠了,罪过! 最近看到有同事也开始用上了微信公众号写博客了,挺好的~给他们点赞,这博客我...
    码农戏码阅读 5,946评论 2 31
  • 这篇文章是我之前翻阅了不少的书籍以及从网络上收集的一些资料的整理,因此不免有一些不准确的地方,同时不同JDK版本的...
    高广超阅读 15,528评论 3 83
  • JVM架构 当一个程序启动之前,它的class会被类装载器装入方法区(Permanent区),执行引擎读取方法区的...
    cocohaifang阅读 1,644评论 0 7