了解Java垃圾收集(GC)

了解Java中的垃圾回收(GC)的工作原理有什么好处?满足软件工程师的求知欲是一个正当的理由,不仅如此,了解GC的工作原理也可以帮助您编写更好的Java应用程序。

这是我个人的非常主观的看法,但是我相信精通GC的人往往是更好的Java开发人员。如果您对GC流程感兴趣,则意味着您具有开发特定大小的应用程序的经验。如果您仔细地考虑过选择正确的GC算法,则意味着您完全了解所开发应用程序的功能。当然,对于优秀的开发人员来说,这可能不是通用的标准。但是,当我说理解GC是成为一名出色的Java开发人员的要求时,很少有人会反对。 

这是“ 成为Java GC专家 ”系列文章中的第一篇。这次我将介绍GC,在下一篇文章中,我将讨论分析特定的GC状态和调优示例。

在学习GC之前,您应该了解一个术语。术语是STW( Stop The World )。意味着JVM需要停止运行应用程序以执行GC。这意味着除GC所需的线程以外的所有线程都将停止其任务,无法处理外部响应。。被中断的任务将仅在GC任务完成后才能恢复。无论您选择哪种GC算法,STW都会发生。GC调优通常意味着减少STW时间。

分代垃圾收集 

Java没有显式释放内存的操作。有人将相关对象设置为null或使用System.gc()方法显式释放内存,这是不合适的。调用System.gc()方法将触发垃圾回收,极大地影响系统性能。将对象设为null其实在大多种场景下没有任何意义。

在Java中,由于开发人员未明确删除程序代码中的内存,因此垃圾收集器会找到不再需要的(垃圾)对象并将其删除。该垃圾收集器是基于以下两个假设创建的。

1、大多数新创建的对象生命周期都很短

2、从老对象到新对象的引用数量很少。

这些假设称为分代假设。基于此,在HotSpot VM实现中将其从物理上分为年轻代老年代

年轻代(Yong Gen):大多数新创建的对象都位于此处。由于大多数对象很快变得无法访问,因此许多对象是在年轻一代中创建的,然后死亡了。当回收年轻代对象时,我们称之为“ Minor GC ”。

年老代(Old Gen):从年轻代幸存下来的对象复制到此处。它通常比年轻一代大。同时一些大对象也在此分配。由于它的大小较大,因此与年轻一代相比,GC发生的频率会降低,耗时会更久。当回收老年代对象时,我们说发生了“  Major GC ”(或“ Full GC ”)。

见下图:

图1:GC区域和数据流。

上表中的永久代也称为“ 方法区域 ”,它存储类或长量字符串。在该区域可能会发生GC,此处发生的GC仍被视为Major GC(Full GC)。 

有人可能会怀疑:

如果老一代的对象需要引用年轻一代的对象怎么办?

为了处理这些情况,在年老代中有一个称为“ 卡片表 ”的东西,它是一个512字节的块。每当年老代中的对象引用年轻一代中的对象时,该对象都会记录在此表中。当为年轻代执行GC时,仅搜索此卡表以确定它是否适用于GC,而不是检查年老代中所有对象的引用。

图2:卡片表结构。

年轻代的组成

年轻代是第一次创建对象的地方。年轻一代分为3个空间。 

一个 Eden

两个 Survivor(From,To)

总共有3个区,其中两个是幸存者区。每个区的执行过程顺序如下:

1、大多数新创建的对象位于Eden区中。

2、在Eden区中进行一次GC之后,将幸存的对象移动到其中一个Survivor区。 

3、在Eden区进行GC之后,将这些对象堆积到Survivor区中,该区中已经存在其他幸存的物体。

4、一旦Survivor区已满,就将幸存对象移动到另一个Survivor区。然后,已满的Survivor区将更改为完全没有数据的状态。

在这些步骤中幸存下来的对象(已重复多次)被移到了年老代。

通过检查这些步骤可以看到,Survivor区之一必须保持为空。

下表显示了通过次要GC收集到旧数据中的数据的过程:

图3:GC前和后。

在HotSpot VM中,使用两种技术来加快内存分配。一个称为“ 碰撞指针 ”,另一个称为“ TLAB(线程本地分配缓冲区)”。 

指针碰撞技术跟踪分配给Eden区的最后一个对象。该物体将位于Eden区的顶部。并且如果之后创建了一个对象,则仅检查该对象的大小是否适合Eden空间。如果上述对象看起来正确,它将被放置在Eden空间中,新对象将位于顶部。因此,在创建新对象时,仅需要检查最后添加的对象,从而可以更快地分配内存。但是,如果我们考虑多线程环境,则情况就不同了。为了将多个线程使用的对象保存在Eden空间中以确保线程安全,将发生不可避免的锁定,并且由于锁定竞争而导致性能下降。TLAB 是HotSpot VM中解决此问题的方法。这允许每个线程在其Eden空间中有一小部分与其对应的份额相对应。由于每个线程只能访问自己的TLAB,因此即使是“撞球指针”技术也可以在没有锁的情况下分配内存。 

年老代GC

当堆空间不够用时会发生年老代GC。年老代GC的执行过程根据GC策略类型的不同区别很大。对于JDK 7,8,有5种GC类型。 

1、Serial GC - 串行GC

2、Parallel GC - 并行GC

3、Parallel Old GC (Parallel Compacting GC) 

4、Concurrent Mark & Sweep GC  (or "CMS") 

5、Garbage First (G1) GC

其中,Serial GC不得在运行服务器上使用。当台式计算机上只有一个CPU内核时,就会创建此GC类型。使用此串行GC将大大降低应用程序性能。 

现在让我们了解每种GC类型。

串行GC(-XX:+ UseSerialGC)

年轻一代中的GC使用我们在上一段中介绍的类型。老一代的GC使用一种称为“ mark-sweep-compact ” 的算法。

标记-清除-整理算法会将清理后的堆的整理成连续的内存空间。

串行GC适用于较小的内存和少量的CPU内核。


并行GC(-XX:+ UseParallelGC)

图4:串行GC和并行GC之间的区别。

从图片中,您可以轻松地看到串行GC和并行GC之间的区别。串行GC仅使用一个线程来处理GC,而并行GC使用多个线程来处理GC,因此速度更快。当有足够的内存和大量内核时,此GC很有用。也称为“ 吞吐量GC”。 

并行旧GC(-XX:+ UseParallelOldGC)

从JDK5开始支持。与并行GC相比,唯一的区别是年老代的GC算法相对复杂。它经历了三个步骤:标记–摘要–整理

CMS GC(-XX:+ UseConcMarkSweepGC)

图5:串行GC和CMS GC

从图片中可以看到,CMS比到目前为止我所解释的任何其他GC类型都要复杂得多。早期的初始标记步骤很简单。在最接近类加载器的对象中搜索尚存的对象。因此,暂停时间很短。在并发标记步骤中,跟踪并检查了刚被确认的存活对象所引用的对象。此步骤的不同之处在于,它是在同时处理其他线程的同时进行的。在重新标记步骤中,将检查并发标记步骤中新添加或停止引用的对象。最后,在并发收集中步骤,将执行垃圾收集过程。在仍在处理其他线程时执行垃圾回收。由于以这种方式执行此GC类型,因此GC的暂停时间非常短。CMS GC也称为低延迟GC,在所有应用程序的响应时间至关重要时使用。 

CMS的一大有点是缩短了STW时间,但它也具有以下缺点:

1、它比其他GC类型使用更多的内存和CPU。

2、默认情况下不提供压缩步骤,容易导致内存碎片

使用此类型之前,您需要仔细检查。另外,如果由于内存碎片过多而需要执行压缩任务,那么STW时间可能比任何其他GC类型都要长。您需要检查压缩任务执行的频率和时间。

G1 GC

最后,让我们了解G1 GC。 

图6:G1 GC的布局。

如果您想了解G1 GC,请忘记所有有关年轻一代和老一代的知识。如您在图片中看到的,将一个对象分配给每个Region,然后执行GC。G1 GC是基于停顿时间为目标的回收算法,以最大程度的减少STW

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

推荐阅读更多精彩内容