初學者或初級程序員在面試時如果能證明自己具有分析內存用量和內存調優的能力,這相當有利,因為這是針對5年左右相關經驗的高級程序員的要求。
如果在面試時面試官主動問及這方面的問題,大家可以按照如下的思路由淺入深地依次闡述,如果沒問,大家也可以用到下面提及的方法毫無痕跡地(不突兀不顯擺)展示自己這方面的能力。
1 從虛擬機體系結構引出內存管理的話題
如果面試官問,“你是否了解虛擬機體系結構”,那么大家可以按9.1提到的內容,先畫出虛擬機的各部件,隨后依次說明各部分的作用。
其實面試官也知道這部分對項目開發的幫助並不大,所以大家不用過於深入,比如可以不用深入回答.class字節碼文件的結構和類加載器的流程(由於實用性不強,本文也沒講)。但大家一定得總結性地說出靜態數據、基本數據類型和引用等數據的存儲位置,這部分的內容我們在9.1.3部分講過。這樣就能引出后面的關於“內存”的話題。
如果面試官沒有問及虛擬機體系結構的問題,那么也不要緊,畢竟這塊知識點實用性一般,說出來屬於錦上添花。但大家應當通過后文給出的方法,找機會引出“內存“這個話題。
2如何自然地引出內存話題
一般來說,大多數面試官會問垃圾回收的流程,這樣大家就有機會通過堆結構說出垃圾回收的流程,進而展示自己內存調優方面的能力。
或者大家可以更保險點,在簡歷的最近項目介紹里加上類似這樣描述,“這個項目的內存要求比較高,雖然在項目里分配的對象不少,但這個項目只被分配了1G內存,所以在這個項目里,我實踐了一些定位排查內存問題的技能,也做了些調優的工作“,這樣面試官見到簡歷的描述,就會自然而然地提問了。
更穩妥的方法是,在面試中總會有“項目介紹”這個環節,面試官會讓候選人介紹最近的(或最拿得出手)的一個項目,這樣大家就可以順勢說出剛才已經給出的描述。
或者,大家可以在回答數據庫或集合等方面的問題時引出這個話題,比如回答完JDBC問題后,大家可以說一句,“用好的Connection對象我們會及時關閉,否則它所占用的內存對象無法被GC回收”,或者在談及List等集合類型時,同時多說一句,“用好的集合對象我們會及時clear掉,否則這個集合也會對一些對象產生強引用,這樣就會延遲對象的回收時間”。
總之,內存調優這方面的能力不說出來未免有些可惜,大家可以根據上述的描述舉一反三,在面試中找一切可以的機會引入這個話題。
不過這里也請大家注意些技巧,別自說自話地一股腦地全說,這樣反而過猶不及。打個非常不恰當的比方,就像釣魚,大家可以先下個餌,比如在介紹項目時先粗略地提到自己做過這方面的事情,但先別說具體的,等面試官主動問了,再具體地按下文給出的思路一一展開。
萬一面試官在大家的再三暗示下還是沒接口繼續問(雖然這種可能性非常小),那說明面試官真的對此沒興趣,或者說你應聘的公司對此沒需求,那么大家就只能此打住了。
3 根據堆區結構,闡述垃圾回收的流程
在找到合適的機會后,大家可以先從堆的結構入手,進而詳細說明垃圾回收的流程。比如大家被問到,你對Java中的垃圾回收機制了解多少?或者當你說出在項目里你做過內存調優,面試官進一步讓你說出細節,那么大家可以按次序說出如下的要點。
1 可以先說下,new出來的對象都放在堆區里。
2 可以說下堆的結構,比如堆里分年輕區,年老區和持久區,年輕區里還分伊甸區和兩個緩沖區,持久區主要存放的是Java類信息或在代碼里通過import引入的類信息,垃圾回收流程主要涉及到的是年輕和年老區。
3 可以說下垃圾回收的一般流程,比如什么時候會觸發輕量級回收,什么時候會觸發Full GC。
4 可以說下虛擬機是憑什么判斷對象可以被回收(對象上沒有強引用,則會在下次GC流程時被回收),也可以說下“引用計數法”和“根搜索算法”以及它們的差別。
5 可以說下,程序員可以通過System.gc()來啟動Full GC,但Full GC並不是在調用和這個方法后就啟動。不過根據實踐,兩者的時間間隔不會太長。
在說完上述要點后,大家最后一定得引出下一個“內存調優”這個話題,比如可以說,“雖然說Java虛擬機能自動回收內存,但在平時寫代碼時,我們會遵循一些要點來提升內存性能,在項目里,我們還會監控內存使用量,而且我在項目里也有過排查OOM問題的經驗“。這樣的話就能進一步展示自己的“調優和排查”能力。
4 再進一步說明如何寫出高性能的代碼
我們之前提到過這方面技能,這里來總結一下要點,在面試時,大家可以在閱讀本章相關內容的基礎上自行展開敘述。
1 物理對象(比如Connectio或IO)用好之后得及時close。
2 大的對象用好后應當及時設置成null,以撤銷強引用。
3 集合對象用好后應當及時clear。
4 盡量別頻繁地使用String(或其它不變類)對象,這樣容易產生內存碎片。
5 盡可能地使用軟和弱引用,因為這樣能提早對象的被回收時間。
6 不建議重寫finalize方法。
7 可以通過調整命令行參數來調整堆內存的性能,但同時請注意,在項目里一般只會修改-Xms或-Xmx參數,或者再加一些日志打印和保存Dump文件的參數。在修改其它參數時,項目組一般會很慎重,所以大家可以說自己了解其它的參數,但如果沒有十足的把握,別說自己在項目里調整過類似於“設置年輕區與年老區的比值”等容易產生內存問題的參數。
解決問題相對容易,但定位問題就相對難了,所以建議大家可以再進一步展示自己“監控、定位和調優”方面的能力,比如可以通過如下的敘述引入到這個話題,“除了這些代碼上的技巧外,我們在項目上線后還必須監控內存使用量,一旦發生OOM或Stop The World等問題,我們得通過一定的方法來定位問題點,從而再用剛才提到的技巧來優化內存”。
5 最后展示監控、定位和調優方面的綜合能力
在面試時,面試官是沒法當場給出一個實際的問題讓大家來現場解決,只要候選人敘述得不離譜,一些要點能說上來,一般就會認為候選人具備這方面的能力。
這塊大家可以說,比如通過JConsole確認有內存問題,通過Dump文件來查看OOM的現場,從而再通過GC日志和代碼里輸出的內存使用量來定位問題點。在面試前,建議大家多看一些GC日志文件和Dump文件,這樣在敘述時就更會胸有成竹了。
通過閱讀這個章節,大家一定能體會到,“內存監控、定位和調優”方面的能力並不難學,也不難准備面試中的說辭,而且在面試中,最多用上五分鍾就能把這部分的知識點說全,但大家一旦按上述思路展示出了這方面能力,那么很大程度能改變面試官對你的評價。
根據我們的面試經驗,初級程序員的平均能力其實差不了多少,在很多時候我們是無法取舍的。比如我們要從10個人里招5個人進來,除去特別好的(一般2個)和特別差的(一般也是2個),有6個人的綜合能力(包括學校背景工作背景項目經驗和面試結果)是差不多的,也就是說我們很難從這6個人里挑選出3個人。
這時,如果這6人中誰有類似於內存調優(或者前章提到的設計模式)等方面的加分項,那么就一定會優先考慮這個人。