(4)垃圾收集器与内存分配策略

本节常见面试题(推荐带着问题阅读,问题答案在文中都有提到):

如何判断对象是否死亡(两种方法)。

简单的介绍一下强引用、软引用、弱引用、虚引用(虚引用与软引用和弱引用的区别、使用软引用能带来的好处)。

垃圾收集有哪些算法,各自的特点?

HotSpot为什么要分为新生代和老年代?

常见的垃圾回收器有那些?

介绍一下CMS,G1收集器。

Minor Gc和Full GC 有什么不同呢?

7.两种垃圾回收,实际用哪种?

8.标记清扫,为嘛要标记那些标记的东西?怎么找那些存活的标记?

-----------------------------------------------------------------------

1.首先所需要考虑

2 对象已经死亡?

   2.1引用计数法

   2.2可达性分析算法

   2.3 再谈引用

   2.4 生存还是死亡

   2.5 回收方法区

3 垃圾收集算法 

   3.1 标记-清除算法

   3.2 复制算法

   3.4分代收集算法

4 垃圾收集器

   4.1 Serial收集器

   4.2 ParNew收集器

   4.3 Parallel Scavenge收集器

   4.4.Serial Old收集器 

   4.5 Parallel Old收集器

   4.6 CMS收集器

   4.7 G1收集器

5 内存分配与回收策略 

   5.1对象优先在Eden区分配 

   5.2 大对象直接进入老年代 

   5.3长期存活的对象将进入老年代 

   5.4 动态对象年龄判定 

总结

一、概述

首先所需要考虑:什么时候回收?那些垃圾需要回收?如何回收?

排查各种 内存溢出问题、当垃圾收集称为系统达到更高并发的瓶颈时,对这些“自动化”的技术监控和调节。

二、对象已经死亡

中几乎放着所有对象实例回收前判断是否死亡(不能再用的对象)

2.1引用计数法

引用,计数器加1引用失效减1;计数器为0对象就是不可能再被使用

简单,效率高,虚拟机没用这个管理内存,因难解决对象之间相互循环引用问题。

打印垃圾回收简易信息的参数:-verbose:gc

打印详细:-verbose:gc -XX:+PrintGCDetails

输出:[GC (System.gc()) [PSYoungGen: 22476K->680K(38400K)] 42956K->21168K(125952K), 0.0008355 secs]可以看出对象被回收,因此Java不使用引用计数算法。

2.2可达性分析算法

“GC Roots”的对象作为起点,向下搜索,节点所走过路径为引用链对象到GC Roots没有任何引用链相连,此对象不可用。

可作为GC Roots的对象:

    虚拟机栈(方法中的引用对象)、本地方法栈(Java方法)中引用对象

    方法区的类(static类)、常量属性(final)所引用对象

2.3 再谈引用

1.强引用

大部分都是强引用,生活必需品,垃圾回收器绝不会回收它内存空间不足OutOfMemoryError,程序异常终止,也不回收强引用。

2.软引用(SoftReference)

内存不足了,回收。实现内存敏感高速缓存。OOM时二次回收

和引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,JAVA虚拟机就会把这个软引用加入到与之关联的引用队列中。

3.弱引用(WeakReference)

发现就回收。和一个引用队列(ReferenceQueue)联合使用,同上

4.虚引用(PhantomReference)

任何时候都可能被垃圾回收。跟踪对象被垃圾回收活动

与软、弱引用区别:必须和引用队列(ReferenceQueue)联合使用。发现有虚引用,回收之前,把虚引用加入引用队列。判断引用队列中是 否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。

很少使用弱引用与虚引用,软引用较多,可加速回收速度,维护运行安全,防止内存溢出(OutOfMemory)

2.4 生存还是死亡

不可达的对象,b是“非死不可”的,暂时处于“缓刑阶段”,真正死亡两次标记

(1)可达性分析,筛选条件:标记且筛选,是否有必要执行finalize方法。也是作为第二次标记的条件。对象没有覆盖finalize方法,或finalize方法已经被虚拟机调用过时,虚拟机将这两种情况视为没有必要执行。

(2)finalize方法(只能做一次)被放在队列中第二次标记,除非与引用链上对象关联,否则就会被真的回收。

2.5 回收方法区

Hotspot虚拟中永久代,回收(1)废弃常量和(2)无用的类。回收性价比低,一般新生代能回收70-85%

(1)如程序中没有String对象是"abc",这时候GC,"abc"常量被清理

(2)“无用的类”同时满足下面:

1.所有实例被回收,堆中不存在

2.加载该类ClassLoader被回收。

3.类对应java.lang.Class对象没有被引用

3 垃圾收集算法 

3.1 标记-清除算法

统一回收所有被标记对象。基础收集算法,效率空间问题(大量不连续碎片) 空间不足提前触发GC


3.2 复制算法

解决效率问题,内存分为大小相同两块每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制另一块去,然后再把使用的空间一次清理掉。每次内存回收都是对内存区间的一半进行回收

改良版

新:老年代对象 = 8:1,不用1:1,Eden和2个Survivor区比例为8:1,新生代占到9/10,老年代不存在复制算法

3.4分代收集算法

新生代复制老年代存活几率“标记-清理

延伸面试问题: HotSpot为什么要分为新生代和老年代?

4 垃圾收集器

内存回收具体实现根据具体场景选择

4.1 Serial收集器

 “单线程” “Stop The World” ,Client模式下的虚拟机来说是个不错的选择。

主要参数:

-XX:SurvivoRatio:新生代Eden和Survivor区(单个Survivor)容量比值,默认8

-XX:PretenureSizeThreshold:直接晋升到老年代对象大小,大于该值对象直接在老年代分配。

-XX:HandlePromotionFailure:允许老年代分配担保失败,开启后可冒险YGC。

4.2 ParNew收集器

Serial多线程版本,运行Server模式下首要选择,除Serial外,只它能与CMS收集器(真正意义上的并发收集器)配合工作。


并行和并发概念补充:

并行(Parallel) :线程并行工作,用户线程等待状态

并发(Concurrent)用户线程垃圾收集线程同时执行不一定并行,可能交替执行),用户程序在运行垃圾收集器运行另一个CPU上

4.3 Parallel Scavenge收集器

Parallel(平行) Scavenge(清扫)新生代收集器,复制算法

吞吐量 = (执行用户代码时间)/(执行用户代码时间+垃圾回收占用时间)

关注点是吞吐量(高效率用CPU)。提供参数找到最大吞吐量

-XX:MacGCPauseMillis:最大垃圾收集停顿时间

-XX:GCTimeRatio:吞吐量大小

GCTimeRatio=99,最大垃圾收集时间占比为1/(1+99)=1%,GCTimeRatio=用户代码运行时间/GC时间。

-XX:+UseAdaptiveSizePolicy:动态自适应调整JVM参数(-Xmn、SurvivorRatio等)

4.4.Serial Old收集器 :Serial老年代版本,单线程收集器

4.5 Parallel Old收集器:Parallel Scavenge收集器的老年代版本

4.6 CMS收集器

CMS(Concurrent Mark Sweep)关注点用户线程停顿时间。

(1)初始标记:找GC Roots,暂停其他线程

(2)并发标记:找引用链

(3)重新标记:找变更

(4)并发清除:开启用户线程,GC线程清扫标记

(1)(3):stop the world

(2)(4):与用户线程并发

缺陷:

(1)占用大量cpu资源

(2)无法处理“浮动垃圾” :并发清除阶段,用户线程产生对象。

-XX:CMSInitiatingOccupancyFranction:老年代被使用的百分比,达到时触发GC(老年代占满了再GC,GC并发产生对象可能获取不到存储空间)

CMSInitiatingOccupancyFranction过高会导致大量Concurrent Mode Failure,即老年代预留内存无法满足需要。

(3)内存空间碎片

-XX:+UseCMSCompactAtFullCollection:FullGC时启动内存碎片的合并整理

-XX:CMSFullGCsBeforeCompaction:执行多少次不压缩的FullGC后压缩一次,默认为0。即每次FullGC时都合并整理内存碎片。

并发清除

4.7 G1收集器

削弱新生代与老年代概念,将堆划分不同Region,根据回收价值,确定优先列表。

整体“标记-整理”局部(两个Region之间)“复制”算法

多个CPU缩短stop-The-World时间。原本停顿GC动作,并发继续执行。 

面向服务器,对配备多颗处理器及大容量内存机器. 高概率满足GC停顿时间,备高吞吐量性能

(串行serial, 并行parallel, CMS)把堆内存划分: 年轻代(young generation), 年老代(old generation), 持久代(permanent generation)


和CMS有很多相似之处。

1.初始标记:仅标记GC Roots直接关联对象,并改TAMS值,让下阶段用户程序并发运行时,能用Region中创建新对象,这段要停顿线程,但很短

2.并发标记:从GC Root开始对堆中对象可达性分析找存活对象耗时长,但可与用户程序并发执行。

3.最终标记:修正上阶段落掉,虚拟机将这段对象变化记录在线程Remenbered Set Logs里,Remembered Set Logs的数据合并到Remembered Set中,要停顿线程,可并行执行。目的:

4.筛选回收:对各个Region的回收价值和成本进行排序,根据用户所期望GC停顿时间制定回收计划

5 内存分配与回收策略 

5.1对象优先在Eden区分配 

Eden区没空间,虚拟机将发起Minor GC

1)Minor Gc和Full GC 有什么不同呢?

新生代GC(Minor GC):    1)EdenSurvivor区,2)无法为新生对象分配内存时,触发Minor GC。3)频繁,回收速度快。新生代中大多数对象的生命周期都短

老年代GC(Full GC):   1)对整个新生代、老生代、元空间(metaspace,java8以上版本取代perm gen)全局GC。2)用了什么垃圾收集器,才能解释是什么样gc ,不等于Major GC,也不等于Minor GC+Major GC,3)

Major GC :清理Tenured区,回收老年代,伴随至少一次Minor GC(并非绝对),速度慢10倍

2)如果老年代对象引用年轻代对象,年轻代对象是否被GC?

写屏障,确保新被老引不被gc:

年代存活对象较时,每次Minor GC查年代所有对象影响回收效率(因为GC会 stop-the-world),老年代有write barrier(写屏障)管理card table(卡表),card table存放了所有老对新生代对象引用

3)如何判断老引用新?

年轻代之间对象引用消除,计数器>1则被引用

5.2 大对象直接进入老年代 

大对象需要大量连续内存空间(如:字符串、数组)。

5.3长期存活的对象将进入老年代 

为识别哪些应放新、老年代中。虚拟机给每个对象,年龄(Age)计数器。

Survivor空间中,并且对象年龄设为1。一次Minor GC,年龄加1

-XX:MaxTenuringThreshold最大年龄,默认为15;

5.4 动态对象年龄判定 

Survivor中相同年龄所有对象大小总和超过Survivor一半,大于或等于该年龄直接进入老年代。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容