java垃圾收集

转载、引用请标明出处
https://www.jianshu.com/p/8ec0ee8ca7ee
本文出自zhh_happig的简书博客,谢谢

以下内容,是本人学习的笔记和工作中的总结,仅供大家参考,有误的地方还请指正

一 判定垃圾对象算法

  • 引用计数法
    • 在对象中添加一个计数器,记录着指向对象的引用的个数
    • 当有新的引用指向这个对象的时,计数器+1,当指向对象的引用被置null时,计数器-1
    • 当计数器的值为0,那么这个对象就是垃圾对象,就会被垃圾回收器回收
    • 缺陷:当对象1中有引用指向对象2,对象2中有引用指向对象1,但是再也没有其他外部引用指向对象1和对象2,对象1、对象2是垃圾对象。通过引用计数法,对象1、对象2计数器都为1,不会被垃圾回收器回收。
    • 不推荐使用
  • 可达性分析法
    • 该算法的基本思路就是通过GC Roots对象作为起点,从这些节点开始向下搜索
    • 搜索走过的路径被称为引用链
    • 当一个对象,从GC Roots节点向下搜索,没有任何一条路径能够达到该对象,那么这个对象就是垃圾对象
    • 可以做为GC Roots的对象包括
      • 虚拟机栈中引用指向的对象
      • 方法区中类静态属性所引用的对象
      • 方法区中常量所引用的对象
      • 本地方法栈中引用的对象

二 垃圾回收算法

  • 标记-清除算法
    • 分为标记和清楚2步
    • 标记:就是通过可达性分析法将对象标记为垃圾对象
    • 清除:将垃圾对象回收
    • 缺点:存在效率问题和空间问题
      • 垃圾对象在堆内存中是散乱的,被清除之后,会导致越来越多不连续的空间,当分配大对象时,要寻找一片合适的内存空间,就会变得困难
      • 如果找不到合适的内存空间存放这个大对象,就会触发一次GC,影响性能
  • 复制算法
    • 年轻代的垃圾收集算法,在年轻代对象存活率低,复制算法效率很高
    • 将堆内存分成2部分,只在其中一部分中分配内存
    • 垃圾回收后,把存活的对象复制到另一部分内存连续的空间上
    • 就这样在2个内存中循环复制,这样解决了 标记-清除算法 中的效率问题
    • 缺点:由于只在其中一部分中分配内存,存在内存浪费问题
      • 再将内存细分,即可降低内存浪费,详见Eden、Survivor 0 、Survivor 1、Tenured
  • 标记-整理算法
    • 年老代的垃圾收集算法
    • 在年老代对象存活率高,复制算法效率低,使用标记-整理算法
    • 标记过程仍然与“标记-清除”算法一样,
    • 整理:不是直接清除,而是对内存里面的对象进行重新整理,让所有存活的对象都向一端移动,依次排列,那么端边界另一边的就都是垃圾对象了,直接清理掉
    • 标记-整理算法唯一的缺点就是效率也不高,不仅要标记所有存活对象,还要整理所有存活对象的引用地址。从效率上来说,标记-整理算法要低于复制算法。
  • 分代收集算法
    • 根据不同的内存区选择不同的算法
    • 在年轻代,选择复制算法
    • 在年老代,选择标记-整理算法

三 垃圾回收器

  • Serial
    • 年轻代垃圾收集器,采用复制算法
    • 串行收集器:如果serial要收集垃圾,必须让程序其他线程停掉,收集完毕,程序其他线程继续执行
    • 单线程垃圾收集器:serial单线程收集垃圾
    • 整体效率低
  • Serial Old
    • 它是Serial收集器的年老代版本,与Serial相似,区别是使用“标记-整理”算法
  • Parnew
    • 年轻代垃圾收集器,采用复制算法
    • 串行收集器:如果parnew要收集垃圾,必须让程序其他线程停掉,收集完毕,程序其他线程继续执行
    • 多线程垃圾收集器:parnew多线程收集垃圾
  • Parallel scavenge
    • 与parnew类似,区别是parallel scavenge能控制吞吐量
    • 吞吐量 = 执行用户代码的时间 / (执行用户代码的时间 + 垃圾回收所占用的时间)
      • -xx:MaxGCPauseMillis 垃圾收集器停顿最大时间,就是垃圾收集线程(多线程)收集垃圾的时间,是不是设置越小就越好呢?假设设置100ms,垃圾收集器分配的内存可能是1G,设置为1ms,垃圾收集器分配的内存可能只有10M,因为只有10M这么小的内存才能在1ms内收集完,那么10M内存显然太小了,就会造成垃圾频繁回收。原来100ms回收一次的任务,现在如果1ms回收一次,可能要频繁回收80次,对比之下性能并没有多大提升。所以不是设置的越小越好,应该更具实际情况设置一个合理值。
      • -xx:CGTimeRatio 吞吐量大小
    • 适用注重吞吐量的后端服务
  • Parallel Old
    • 是Parallel Scavenge收集器的年老代版本,与Parallel Scavenge相似,但与Parallel Scavenge不同的是,它使用的是“标记-整理算法”
    • 使用方式:-XX:+UseParallelOldGC,打开该收集器后,将使用Parallel Scavenge(年轻代)+Parallel Old(年老代)的组合进行GC
  • CMS
    • 年老代、永久代垃圾收集器,采用标记-清除算法
    • 并行收集器:垃圾收集线程可以和程序其他线程并发执行
    • 多线程垃圾收集器:CMS多线程收集垃圾
    • 工作过程
      • 初始标记:造成程序其他线程停顿。标记垃圾对象
      • 并发标记:与程序线程并发运行。在运行期间会发生对象的引用变更等等情况,对于这些对象,都是需要进行重新标记的,否则会发生漏标的情况。这个阶段因为是并发的容易导致concurrent mode failure
      • 重新标记:会造成程序其他线程停顿。重新标记的内存范围是整个堆,包含young_gen和old_gen。为什么要扫描新生代呢,因为对于老年代中的对象,如果被新生代中的对象引用,那么就会被视为存活对象,即使新生代的对象已经不可达了。所以需要标记young_gen和old_gen。
      • 并发清理:与程序线程并发运行。并发清理阶段用户线程还在运行着,伴随程序运行自然就还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只好留待下一次GC时再清理掉。这一部分垃圾就称为“浮动垃圾”。
      • 并发重置:与程序线程并发运行。重新设置CMS算法内部的数据结构,准备下一个CMS生命周期的使用
    • 优点
      • 并发收集
      • 低停顿:只有初始标记和重新标记会造成程序其他线程短暂停顿
    • 缺点
      • 占用大量的cpu资源
      • 无法处理浮动垃圾
      • 出现Concurrent Mode Failure
      • CMS收集与应用线程会同时增加对堆内存的占用,也就是说,CMS必须要在老年代堆内存用尽之前完成垃圾回收,否则CMS回收失败,出现Concurrent Mode Failure;
      • 年老代的剩余空间无法满足新对象的空间分配,也会出现这个错误
      • 在出现Concurrent Mode Failure时,将触发担保机制,Serial Old收集器将会以STW的方式进行一次full gc,从而造成较大停顿时间,影响性能
  • G1(Garbage First)
    • JDK7增加,成为HotSpot重点发展的垃圾回收技术,被HotSpot团队寄予取代CMS的使命
    • 将会被安排成为JDK9的默认垃圾收集器
    • 并行收集器:垃圾收集线程可以和程序其他线程并发执行
    • 多线程垃圾收集器:G1多线程收集垃圾
    • 详见G1垃圾收集器

四 垃圾回收器作用内存区域以及他们之间的组合关系

  • 7种不同分代的收集器
    • Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1;
  • 垃圾收集器所属区域
    • 年轻代收集器:Serial、ParNew、Parallel Scavenge
    • 年老代收集器:Serial Old、Parallel Old、CMS
    • 整堆收集器:G1
  • 两个收集器间有连线,表明它们可以搭配使用
    • Serial/Serial Old
    • Serial/CMS
    • ParNew/Serial Old
    • ParNew/CMS
    • Parallel Scavenge/Serial Old
    • Parallel Scavenge/Parallel Old
    • G1

以上内容,是本人学习的笔记和工作中的总结,仅供大家参考,有误的地方还请指正

转载、引用请标明出处
https://www.jianshu.com/p/8ec0ee8ca7ee
本文出自zhh_happig的简书博客,谢谢

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

推荐阅读更多精彩内容