1. 程式人生 > >面試題 java垃圾回收機制

面試題 java垃圾回收機制

前幾天面試的時候被問到垃圾回收機制的時候,心裡還慶幸這個之前看過,可是答完後就傻了,面試官竟然問還有沒有。

好吧,我一直以為面試官是懂我說什麼的,加上說的有點快,有點亂,很多東西都省略掉了,估計是我省略掉的被認為是我不懂的了。

所以組織一下語言,下次儘量說的清楚一點。。

記憶體回收機制:

記憶體回收就是釋放掉在記憶體中已經沒用的物件。

首先,要判斷怎樣的物件是沒用的物件。這裡有2種方法:

1.採用標記計數的方法:

給記憶體中的物件給打上標記,物件被引用一次,計數就加1,引用被釋放了,計數就減一,當這個計數為0的時候,這個物件就可以被回收了。當然,這也就引發了一個問題:迴圈引用的物件是無法被識別出來並且被回收的。所以就有了第二種方法:

2.採用根搜尋演算法:

從一個根出發,搜尋所有的可達物件,這樣剩下的那些物件就是需要被回收的

判斷完了哪些物件是沒用的,這樣就可以進行回收了

最簡單的,就是直接清空那個需要被回收的物件。但是這又出現了一個問題,就是記憶體會被分為一塊一塊的小碎片。

為了解決這個問題,可以採用第二種方法,就是在之前的基礎上將存活的物件給整理一下,使他們變成一個連續的記憶體,從而釋放出連續的較大的記憶體空間。

還有一中回收方法就是採用複製的辦法:將記憶體分為2塊,一塊用來存放物件,另一塊用來放著,當存放物件的那塊滿了以後就將上面存活的物件給複製過來,然後在這塊記憶體上工作,並且將之前的記憶體清空,當自己這塊滿了以後再複製回去,如此反覆。

比較效率的一中做法是將以上的幾種方法給結合起來。

首先將記憶體分塊,分為新生代,老年代和永久代。

永久代用來存放程式碼,等一些基本不改變的資料,

新生代用來存放剛產生的一些物件,新生代又可分為3塊。分別為Edon區,Survivor0,survivor1,剛產生的物件是放在Edon區中,當這個區塊放滿了以後就將其存活的部分複製到survivor0塊中,並且將Edon區中的資料清空,等到survivor0滿了就將其中的存活的資料放到survivor1中,清空survivor0,垃圾回收到了一定次數還未被回收的物件,就可以放到老年區。一般來說,剛才產生的物件大多是要在下一次垃圾回收的時候就要被回收掉的,只有一小部分物件會被保留下來,這些被保留下來的物件都是比較穩定的,所以在老年區中的物件回收方法可以採用整理的方法,而在Edon區等新生代中採用複製的方法比較好。

這裡,基本上就講完了。

萬一被問到還有呢。。想了想,還可以扯些其他方面的:

垃圾回收他是在虛擬機器空閒的時候或者記憶體緊張的時候執行的,什麼時候回收不是由程式設計師來控制的,這也就是java比較耗記憶體的原因之一。

還有在垃圾回收的時候當檢測到物件沒有用了,需要被回收的時候並不會馬上被回收,而是將其放入到一個準備回收的佇列,去執行finalize方法。。然等到下次記憶體回收的時候要是他還是沒有被任何人引用的話,就將其給回收了。(如果在finalize方法中重新給物件加個引用,這樣物件是有可能不會被回收的)不過finalize方法不推薦使用,他跟C++中的解構函式不同,我們既不能確定什麼時候他回被回收,也不能保證這個方法一定會被執行。

好像真的編不出來了。。。