浅析 java 垃圾回收(一)—— 以 HotSpot 为例

java 的垃圾回收也就是我们常说的 gc ( garbage collector )。这是一个老生常谈的问题。之所以这么经常被提及,是因为它对 java 性能有很大影响。

在 c/c++ 中考虑到效率,内存的分配和销毁是由程序员来控制的。程序员使用内存必须手动分配,在使用结束后,在手动释放掉已经不用的内存空间。如果忘记释放内存空间,那么这块内存区域就是一直被占用的状态。其他急需内存的程序将无法使用这块内存,导致内存泄漏

java 中为了减轻程序员的负担,同时为了防止程序员忘记释放内存导致内存泄漏,内存的回收交由垃圾回收器(gc)管理。程序员可以专注于核心业务的编写,不受繁琐的手动分配和释放的打扰。

gc 所做的工作就是,将不再被使用的对象或者不再被引用的对象,所占用的内存空间进行回收。

为了理解 java 的垃圾回收,先来了解一下 java 内存区域

java 的内存区域粗略包括有5个部分

  • 方法区(Method Area)
  • 虚拟机栈(VM Stack)
  • 本地方法栈(Native Method Stack)
  • 堆(Heap)
  • 程序计数器(Program Counter Register)
java 内存区域.png
程序计数器

程序计数器(pc),是 jvm 的一个抽象概念,和 cpu 中的 pc 概念相似。用来记录当前执行的字节码文件的所在行。用来控制程序的执行顺序,进行流程控制。jvm 中的每个线程都拥有一个 pc ,来记录各自执行到的指令位置。

方法区

方法区在 Hotspot JVM 中也称为 permanent generation。与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的应该是与Java堆区分开来。 对于习惯在HotSpot虚拟机上开发、部署程序的开发者来说,很多人都更愿意把方法区称为“永久代”(Permanent Generation),本质上两者并不等价,仅仅是因为HotSpot虚拟机的设计团队选择把GC分代收集扩展至方法区,或者说使用永久代来实现方法区而已,这样HotSpot的垃圾收集器可以像管理Java堆一样管理这部分内存,能够省去专门为方法区编写内存管理代码的工作。

虚拟机栈

和 pc 一样,虚拟栈也是线程私有的。生命周期和线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

本地方法栈

本地方法栈和虚拟机栈相似,但是它是用来记录 Native 方法的。也就是 java 调用的非 java 方法,比如 c/c++

堆是 jvm 内存类中的主要部分,被所有线程共享。所有对象和数组都在这个堆上分配,因此堆是 gc 管理的主要区域。为了有效地实现垃圾回收,堆又被细分为新生代(yong generation)老年代(old generation),新生代又可以再细致地分为 Eden SpaceSurvivor Space。在 Oracle 的 Hopspot JVM 的描述中,也将方法区称为永久代(permanent generation)

Hotspot 中 gc

JVM 只是 java 虚拟机概念或者称它为标准。就像 rfc 文档和具体网络协议实现的之间关系。因此,JVM 有很多的实现,比如我们最熟悉的两种实现 OpenJDKHotSpot

本文讨论的垃圾回收机制以 HotSpot 为例
HotSpot 中的垃圾回收,主要涉及到 heap ,也就是堆区

HotsSpot 使用一种叫世代回收(Generational Garbage Collection)的方法来实现垃圾回收,本文的后面将介绍为什么要分代

为了实现世代回收,HotSpot 把 heap 分为多个区域


分别为新生代老年代,对应于垃圾回收的不同过程,使用不同的回收算法

注:
1、有两个垃圾收集过程,minor garbage collectionmarjor garbage collection
2、在进行垃圾回收的时候,会停止所有在运行的线程被称作 " stop world event "

Hotspot 中的垃圾回收有下面几个步骤

1、新的对象被分配到 eden两个 survivor 分区在开始状态都是空的

2、eden 空间分配满时,就开始执行第一次的 minor garbage collection。将还在被使用的对象移动到 S0,同时删除 eden 中,不再被使用的对象。标记对象 age 为 1。

3、发生下一次的 minor GC 时,将 eden 区中未被使用的对象删除,并将正在使用的对象移动到 survivor 区。需要注意,这个时候把 eden 对象放到 S1,还把 S0 中还被使用的对象移动到 S1。然后,把 age 加 1。

4、再进行下一次 minor GC 时,将 eden 区中未被使用的对象删除,并移动到 S0 区,同时 S1 移动到 S0, age 加 1

5、当对象的 age 达到某个阈值(通常情况为 8),就进行 marjor GC 。把 age 为 8 且还在使用的对象,从 yong generation 移动到 old generation

6、过程总览

为什么要分代?

根据经验分析得到对象特性:

  • 刚创建的对象容易被回收
  • 经过几次回收后还保留的对象,被回收的几率会降低

基于这种分析,可以将堆分为新生代和老生代,针对不同的阶段的特点,采用不同的回收算法来提高回收效率。这就时Hotspot JVM GC 的思想

当一个对象经过几次回收后依然存活,对象就会被放入称为老生代的内存空间。在老生代中,几乎所有的对象都是经过几次垃圾回收后依然得以幸存的。因此,可以认为这些对象在一段时期内,甚至在应用程序的整个生命周期中,将是常驻内存的。如果依然使用复制算法回收老生代,将需要复制大量对象。再加上老生代的回收性价比也要低于新生代,因此这种做法也是不可取的。根据分代的思想,可以对老年代的回收使用与新生代不同的标记-压缩算法,以提高垃圾回收效率。(后续讨论算法)

总结

上面简述了 Hotspot JVM 的 GC,但是没有涉及具体的垃圾回收算法。大概的垃圾回收算法有,引用计数法、标记-清除算法、复制算法、标记-压缩法、增量算法*。浅析 java 垃圾回收(二)—— 回收算法 继续回收算法

参考

[1] Java Garbage Collection Basics
[2] Java深度历险(四)——Java垃圾回收机制与引用类型

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

推荐阅读更多精彩内容