1. 程式人生 > >GC在什麼時候,對什麼東西,做了什麼事情

GC在什麼時候,對什麼東西,做了什麼事情

原文:

https://mp.weixin.qq.com/s?__biz=MzAxNDMwMTMwMw==&mid=2247489508&idx=1&sn=0485418697ff689e2964cc4ff30a7819&chksm=9b9436fcace3bfea8a69ac5312c5ee4bfd960c1080c53f26511d9c50d4b24f433d63a8bbf241&mpshare=1&scene=1&srcid=0930kFrXoVeK61g4GarEE9Te#rd --------------------- 作者:Ontheroad_ 來源:CSDN 原文:https://blog.csdn.net/Ontheroad_/article/details/82905165?utm_source=copy 版權宣告:本文為博主原創文章,轉載請附上博文連結!

一個面試官對JVM面試問題的分析

 

問題:GC在什麼時候,對什麼東西,做了什麼事情

 

什麼時候:

1.系統空閒的時候

這種回答大約佔30%,遇到的話一般我就會轉向別的話題,譬如演算法、SSH看看能否發掘一些他擅長的其他方面

2.系統自身決定,不可預測的時間/呼叫System.gc()的時候

這種回答大約佔50%,大部分應屆生都能回答到這個答案,起碼不能算錯誤是吧,後續應當細分一下到底是語言表述導致答案太籠統,還是本身就只有這樣一個模糊的認識。 

3.能說出新生代、老年代結構,能提出minor gc/full gc

分析:到了這個層次,基本上能說對GC運作有概念上的瞭解,譬如看過《深入JVM虛擬機器》之類的。這部分不足10%。 

4.能說明minor gc/full gc的觸發條件、OOM的觸發條件,降低GC的調優的策略

分析:列舉一些我期望的回答:eden滿了minor gc,升到老年代的物件大於老年代剩餘空間full gc,或者小於時被HandlerPromotionFailure引數強制full gc;gc與非gc時間消耗超過了gcTimeRatio的限制引發OOM,調優諸如通過NewRatio控制新生代老年代比例,通過MaxTenuringThreshold控制進入老年代生存次數等。。。能回答道這個階段就會給我帶來比較高的期望了,當然面試的時候正常人都不會記得每個引數的拼寫,我自己寫這段話的時候也是翻過手冊的。回答道這部分的小於2%。 

 

對什麼東西

1.不使用的物件。 

分析:相當於沒有回答,問題就是在問什麼物件才是“不使用的物件”。大約佔30%。

2.超出作用域的物件/引用計數為空的物件。 

分析:這2個回答站了60%,相當高的比例,估計學校教java的時候老師就是這樣教的。第一個回答沒有解決我的疑問,gc到底怎麼判斷哪些物件在不在作用域的?至於引用計數來判斷物件是否可收集的,我可以會補充一個下面這個例子讓面試者分析一下obj1、obj2是否會被GC掉? 

 
  1. class C{

  2. public Object x;

  3. }

  4. C obj1、obj2 = new C();

  5. obj1.x = obj2;

  6. obj2.x = obj1;

  7. obj1、obj2 = null;

主流的java虛擬機器裡面沒有選用引用計數法來管理記憶體,最主要的原因就是它很難解決物件之間相互迴圈引用的問題

3.從gc root開始搜尋,搜尋不到的物件

分析:根物件查詢、標記已經算是不錯了,小於5%的人可以回答到這步,估計是引用計數的方式太“深入民心”了。基本可以得到這個問題全部分數。 

PS:有面試者在這個問題會補充強引用、弱引用、軟引用、幻影引用區別等,不是我想問的答案,但是可以加分

4.從root搜尋不到,而且經過第一次標記、清理後,仍然沒有復活的物件??

分析:我期待的答案。但是的確很少面試者會回答到這一點,所以在我心中回答道第3點我就給全部分數。 

即使在可達性分析演算法中不可達物件,也是並非是“非死不可”的,這時候它們暫時處於“緩刑”階段,要真正宣告一個物件的死亡,至少要經歷兩次標記過程:如果物件在進行可達性分析後發現沒有與GC Roots相連的引用鏈,那麼將會被第一次標記並且進行一次篩選,篩選的條件是此物件是否有必要執行finalize()方法。當物件沒有覆蓋finalize()方法,或者finalize()方法已經被虛擬機器呼叫過,虛擬機器將這兩種情況都是視為“沒有必要執行”。

如果這個物件被判定為有必要執行finalize()方法,那麼這個物件將會放置在一個叫做F-Queued的佇列之中,並在稍後由一個由虛擬機器自動建立的、低優先順序的Finalizer執行緒去執行它。這裡所謂的“執行”是指虛擬機器會觸發這個方法,但並不承諾會等待它執行結束,這樣做的原因是,如果一個物件在finalize()方法中執行緩慢,或者發生了死迴圈(更極端的情況),將很可能導致F-Queue佇列中其他物件永久處於等待,甚至導致整個記憶體回收系統崩潰。finalize()方法是物件逃脫死亡命運的最後一次機會,稍後GC將對F-Queue中的物件進行第二次小規模的標記,如果物件在finalize()方法中成功拯救自己---只要重新與引用鏈上的任何一個物件建立關係即可,那麼第二次標記時它將被移除出“即將回收”的集合;如果物件這時候還沒有逃脫,那基本上它就真的被回收了。

(《深入理解Java虛擬機器》P66)

 

 

做了什麼事情

最後由一個問題:“做什麼事情”,這個問發揮的空間就太大了,不同年代、不同收集器的動作非常多。

1.刪除不使用的物件,騰出記憶體空間。 

分析:同問題2第一點。40%。 

2.補充一些諸如停止其他執行緒執行、執行finalize等的說明。 

分析:起碼把問題具體化了一些,如果像答案1那樣我很難在回答中找到話題繼續展開,大約佔40%的人。 

補充一點題外話,面試時我最怕遇到的回答就是“這個問題我說不上來,但是遇到的時候我上網搜一下能做出來”。做程式開發確實不是去鍛鍊茴香豆的“茴”有幾種寫法,不死記硬揹我同意,我不會糾語法、單詞,但是多少你說個思路呀,要直接回答一個上網搜,我完全沒辦法從中獲取可以評價應聘者的資訊,也很難從回答中繼續發掘話題展開討論。建議大家儘量回答引向自己熟悉的,可討論的領域,展現給面試官最擅長的一面。 

3.能說出諸如新生代做的是複製清理、from survivor、to survivor是幹啥用的、老年代做的是標記清理、標記清理後碎片要不要整理、複製清理和標記清理有什麼優劣勢等

分析:也是看過《深入JVM虛擬機器》的基本都能回答道這個程度,其實到這個程度我已經比較期待了。同樣小於10%。 

4.除了3外,還能講清楚序列、並行(整理/不整理碎片)、CMS等收集器可作用的年代、特點、優劣勢,並且能說明控制/調整收集器選擇的方式

 

--------------------- 作者:Ontheroad_ 來源:CSDN 原文:https://blog.csdn.net/Ontheroad_/article/details/82905165?utm_source=copy 版權宣告:本文為博主原創文章,轉載請附上博文連結!