【整理】Java垃圾回收机制

一、

取自秦风汉雨的博客:

  1. Java垃圾回收简介   http://youli9056.github.io/blog/java-garbage-collection-introduction/
  2. Java垃圾回收器是如何工作的?  http://youli9056.github.io/blog/java-gc-yuan-li/
  3. 各种类型的Java垃圾回收器  http://youli9056.github.io/blog/types-of-java-garbage-collectors/
  4. Java垃圾回收的监控和分析 http://youli9056.github.io/blog/monitoring-and-analyzing-java-garbage-collection/

原文是翻译过来的,图文并茂,可直接点击过去看。这里仅作摘录笔记。

二、

知乎问答:怎么在面试时回答java垃圾回收机制相关问题?

有2个人的回答都很赞,这表明自己在理论知识和实践上都非常匮乏。

(1)

作者:郭无心

链接:https://www.zhihu.com/question/35164211/answer/68265045
来源:知乎

http://icyfenix.iteye.com/blog/715301

在公司当技术面试官几年间,从应届生到工作十几年的应聘者都遇到过。先表达一下我自己对面试的观点:

1.笔试、面试去评价一个人肯定是不够准确的,了解一个人最准确的方式就是“路遥知马力,日久见人心”。通过一、二个小时内的做题、交流,只是没有其他办法下进行的无奈之举,所以通过了面试不代表有多成功,没通过也不代表有多失败。
2.好的面试官本身交谈的时候就不应当把自己一个居高临下的角色上,应当把自己和应聘者当做两个做技术的人平等的交流,把自己当作权威往往就会受到观点的角度、语言表达、工作领域的惯性的制约。
3.好的考察题目则是大家能经常接触,不同层次的人能有不同层次的答案,能从问题引申出后面继续讨论的话题。

举个例子抛砖引玉,下面这个问题是我以前常问的,从应届生到工作十几年的人都问过:
“地球人都知道,Java有个东西叫垃圾收集器,它让创建的对象不需要像c/cpp那样delete、free掉,你能不能谈谈,GC是在什么时候,对什么东西,做了什么事情?”

我自己分析一下这个问题,首先是“什么时候”,不同层次的回答从低到高排列:

1.系统空闲的时候。
分析:这种回答大约占30%,遇到的话一般我就会准备转向别的话题,譬如算法、譬如SSH看看能否发掘一些他擅长的其他方面。

2.系统自身决定,不可预测的时间/调用System.gc()的时候。
分析:这种回答大约占55%,大部分应届生都能回答到这个答案,起码不能算错误是吧,后续应当细分一下到底是语言表述导致答案太笼统,还是本身就只有这样一个模糊的认识。

3.能说出新生代、老年代结构,能提出minor gc/full gc
分析:到了这个层次,基本上能说对GC运作有概念上的了解,譬如看过《深入JVM虚拟机》之类的。这部分不足10%。

4.能说明minor gc/full gc的触发条件、OOM的触发条件,降低GC的调优的策略。
分析:列举一些我期望的回答:eden满了minor gc,升到老年代的对象大于老年代剩余空间full gc,或者小于时被HandlePromotionFailure参数强制full gc;gc与非gc时间耗时超过了GCTimeRatio的限制引发OOM,调优诸如通过NewRatio控制新生代老年代比例,通过MaxTenuringThreshold控制进入老年前生存次数等……能回答道这个阶段就会给我带来比较高的期望了,当然面试的时候正常人都不会记得每个参数的拼写,我自己写这段话的时候也是翻过手册的。回答道这部分的小于2%。

PS:加起来不到100%,是因为有确实少数直接说不知道,或者直接拒绝回答的= =#

分析第二个问题:“对什么东西”:

1.不使用的对象。
分析:相当于没有回答,问题就是在问什么对象才是“不使用的对象”。大约占30%。

2.超出作用域的对象/引用计数为空的对象。
分析:这2个回答站了60%,相当高的比例,估计学校教java的时候老师就是这样教的。第一个回答没有解决我的疑问,gc到底怎么判断哪些对象在不在作用域的?至于引用计数来判断对象是否可收集的,我可以会补充一个下面这个例子让面试者分析一下obj1、obj2是否会被GC掉?
class C{
public Object x;
}
C obj1、obj2 = new C();
obj1.x = obj2;
obj2.x = obj1;
obj1、obj2 = null;

3.从gc root开始搜索,搜索不到的对象。
分析:根对象查找、标记已经算是不错了,小于5%的人可以回答道这步,估计是引用计数的方式太“深入民心”了。基本可以得到这个问题全部分数。
PS:有面试者在这个问补充强引用、弱引用、软引用、幻影引用区别等,不是我想问的答案,但可以加分。

4.从root搜索不到,而且经过第一次标记、清理后,仍然没有复活的对象。
分析:我期待的答案。但是的确很少面试者会回答到这一点,所以在我心中回答道第3点我就给全部分数。

最后由一个问题:“做什么事情”,这个问发挥的空间就太大了,不同年代、不同收集器的动作非常多。

1.删除不使用的对象,腾出内存空间。
分析:同问题2第一点。40%。

2.补充一些诸如停止其他线程执行、运行finalize等的说明。
分析:起码把问题具体化了一些,如果像答案1那样我很难在回答中找到话题继续展开,大约占40%的人。
补充一点题外话,面试时我最怕遇到的回答就是“这个问题我说不上来,但是遇到的时候我上网搜一下能做出来”。做程序开发确实不是去锻炼茴香豆的“茴”有几种写法,不死记硬背我同意,我不会纠语法、单词,但是多少你说个思路呀,要直接回答一个上网搜,我完全没办法从中获取可以评价应聘者的信息,也很难从回答中继续发掘话题展开讨论。建议大家尽量回答引向自己熟悉的,可讨论的领域,展现给面试官最擅长的一面。

3.能说出诸如新生代做的是复制清理、from survivor、to survivor是干啥用的、老年代做的是标记清理、标记清理后碎片要不要整理、复制清理和标记清理有有什么优劣势等。
分析:也是看过《深入JVM虚拟机》的基本都能回答道这个程度,其实到这个程度我已经比较期待了。同样小于10%。

4.除了3外,还能讲清楚串行、并行(整理/不整理碎片)、CMS等搜集器可作用的年代、特点、优劣势,并且能说明控制/调整收集器选择的方式。
分析:同上面2个问题的第四点。

最后介绍一下自己的背景,在一间不大不小的上市软件公司担任平台架构师,有3年左右的面试官经验,工作主要方向是大规模企业级应用,参与过若干个亿元级的项目的底层架构工作。
2010-07-18

凤舞凰扬 2011-04-11  
  呵呵,作为同行,对你的面试问题提个小建议的说。如果你希望得到你预期的答案,至少是最高层的答案,这样的提问其实不合适的。
  呵呵,你在面试架构师这个层次的人时,你可以直接问他GC的过程就是了。其实作为面试者,遇到许多面试官最头疼的是不知道面试官想了解什么。
FallenAngel 2010-12-13  
gc与非gc时间耗时超过了GCTimeRatio的限制引发OOM,调优诸如通过NewRatio控制新生代老年代比例,通过MaxTenuringThreshold控制进入老年前生存次数等…… 

这些答案按照目前的JDK来说略显非主流了吧,OOM最经常出现的其实还是内存泄露,这里可以引出内存泄漏怎么排查(HeapDumpOnOutOfMemoryError,memory dump).调优诸如通过NewRatio控制新生代老年代比例-NewRatio现在已经不推荐这么调整了,直接-Xmn指定新生代大小就Ok.关键是要通过gc log确定LDS(Live Data Size).通过MaxTenuringThreshold控制进入老年前生存次数---MaxTenuringThreshold这个参数也只是在串行gc的情况下或者并行-XX:-UseAdaptiveSizePolicy的时候可用. 

(2)

作者:叛逆者
链接:https://www.zhihu.com/question/35164211/answer/61481880
来源:知乎

你知道多少回答多少。有什么“怎么”的。如果你不知道的话就是会被刷掉,这就是面试的目的。


作者:RednaxelaFX
链接:https://www.zhihu.com/question/35164211/answer/61500128
来源:知乎

@叛逆者 的回答言简意赅的说中了要害。 知道多少回答多少
假定碰上了一位理性且有足够知识储备的面试官。一个好的面试过程通常是逐步推进的,面试官要通过不断深入的问题来判断被面试者的知识极限在哪里,所以没有必要担心被问到自己不知道答案的问题——那就是你的极限,然而那个极限或许已经可以满足这个职位了。
在被推向极限时,最好能表现出积极思考的状态,有理有据的从一些基本原理出发去推论;此时漫无边际的胡乱回答一通或者畏缩而不回答都容易留下负面印象。

这个问题跟另一个JVM问题的技术要点虽然不同,但是在“面试”意义上有相似之处,题主或许会感兴趣: Java instanceof 关键字是如何实现的? - RednaxelaFX 的回答
关于“面试”的话题,很多我想说的都在那个回答里说了。

从提问的方式看,题主显然更关心的是“如何应对面试”的方面,而不是“GC的知识要点如何学习”的方面。我觉得这两个方面确实都是值得关注的,只关注了两者之一都“不够用”。

以我以前工作的经历:我最初在一个做Java应用开发的组,这个组的业务需求并没有特别需要深入理解JVM与GC。那时听到过坐在附近的同事电话面试的情况。其中有些情况就是面试官自己对GC的了解就不充分,然而还是强行提问,电话那头被面试的同学也就只能支支吾吾的作答,然后面试官还要向对方灌输一下自己对GC错误的认识…听着简直为双方都捉鸡。
——面试官自身水平就并不高的情况自然是存在,而且普遍存在。这种时候被不被刷全看运气/人品…

如果有 充分的知识储备,就可以像开头提到的instanceof那帖那样分析面试官的知识水平和目标答案,然后迎合面试官的水平以及应聘职位的需求去作答。

随便举个例子:如果碰到面试官问:“GC如何判断哪些对象不在作用域?”
首先要立即发现这个问题本身有问题——Java的对象并没有作用域,而是对Java对象的引用有作用域——但是不要一上来就为这种细节跟面试官纠缠。
然后考虑一下到底要回答到怎样程度的细节。像 这段 Java 代码中的局部变量能够被提前回收吗?编译器或 VM 能够实现如下的人工优化吗? - RednaxelaFX 的回答 多半就过于详细,除非是面试JVM开发的职位。简单提一下GC可能通过stack map与runtime沟通,VM可以做活跃分析等等就挺好的。
切记要配合职位需求和现场环境的时间限制作答。

如果碰上胡搅蛮缠的面试官的话,这也正好是个判断到底应不应该去那个公司工作的好机会。

反过来,面试官的水平远高于自己、而且自己高估了自己的水平的情况也十分常见。
典型例子之一就是被面试者粗读过一两本书之后就以为掌握了某个知识领域的所有知识,例如说以为读过《深入Java虚拟机》(Inside the Java Virtual Machine)或《深入理解Java虚拟机》就觉得以及完全掌握了JVM的知识点,就算要开发JVM也没问题了——不,粗读过这两本书离能实际参与JVM研发的程度,距离还有点远。

见过太多状况忍不住想借此回答吐个槽。无论是面试别人的还是被别人面试的,有些人会有根深蒂固的错误认识,是没有办法当场说服的。如果遇到对方是这样的情况,请一定要克制住情绪…抱歉这里我不想举任何实际例子,免得麻烦。
即便对方是错的,或许也可以从对方的错误认知中学习到从不同的角度看问题,回头自己论证对方为何是错的,为何会有这样的错误认识;
而有时候可能其实对方是正确的,反而是自己有根深蒂固的错误认识,等能够发现这点的时候也就学到了东西,何乐而不为。

最后,不以应对面试为而是以实际学以致用为目的的去了解JVM与GC相关的知识的话, 《Java Performance》 是一本很实用的书,可以从它开始摸索学习。
要逐步深入的学习,请见我的两个书单:
  • [Garbage Collection][垃圾回收][自动无用内存单元回收]相关读物
  • 从表到里学习JVM实现
仅供参考。
编辑于 2015-08-30

RednaxelaFX还推荐了书籍和链接,突然觉得高架构的人底子好雄厚,膜拜一下...


三、

书单:

RednaxelaFX推荐的书单:http://www.douban.com/doulist/2545443/


四、

相关问题:


Java instanceof 关键字是如何实现的?

https://www.zhihu.com/question/21574535/answer/18998914


---

醉了,感觉自己啥都不会。。。










你可能感兴趣的:(【整理】Java垃圾回收机制)