天天看點

android面試題java_Android應用開發Android面試題:Java垃圾回收機制和finalize()

本文将帶你了解Android應用開發Android面試題:Java垃圾回收機制和finalize(),希望本文對大家學Android有所幫助。

<

Android面試題:Java垃圾回收機制和finalize()。

1. 垃圾回收的意義

在C++中,對象所占的記憶體在程式結束運作之前一直被占用,在明确釋放之前不能配置設定給其它對象;而在Java中,當沒有對象引用指向原先配置設定給某個對象的記憶體時,該記憶體便成為垃圾。JVM的一個系統級線程會自動釋放該記憶體塊。垃圾回收意味着程式不再需要的對象是”無用資訊”,這些資訊将被丢棄。當一個對象不再被引用的時候,記憶體回收它占領的空間,以便空間被後來的新對象使用。事實上,除了釋放沒用的對象,垃圾回收也可以清除記憶體記錄碎片。由于建立對象和垃圾回收器釋放丢棄對象所占的記憶體空間,記憶體會出現碎片。碎片是配置設定給對象的記憶體塊之間的空閑記憶體洞。碎片整理将所占用的堆記憶體移到堆的一端,JVM将整理出的記憶體配置設定給新的對象。

垃圾回收能自動釋放記憶體空間,減輕程式設計的負擔。這使Java 虛拟機具有一些優點。首先,它能使程式設計效率提高。在沒有垃圾回收機制的時候,可能要花許多時間來解決一個難懂的存儲器問題。在用Java語言程式設計的時候,靠垃圾回收機制可大大縮短時間。其次是它保護程式的完整性, 垃圾回收是Java語言安全性政策的一個重要部份。

垃圾回收的一個潛在的缺點是它的開銷影響程式性能。Java虛拟機必須追蹤運作程式中有用的對象,而且最終釋放沒用的對象。這一個過程需要花費處理器的時間。其次垃圾回收算法的不完備性,早先采用的某些垃圾回收算法就不能保證100%收集到所有的廢棄記憶體。當然随着垃圾回收算法的不斷改進以及軟硬體運作效率的不斷提升,這些問題都可以迎刃而解。

2. 垃圾收集的算法分析

Java語言規範沒有明确地說明JVM使用哪種垃圾回收算法,但是任何一種垃圾回收算法一般要做2件基本的事情:

(1)發現無用資訊對象;

(2)回收被無用對象占用的記憶體空間,使該空間可被程式再次使用。

判斷這兩點比較常見的方法:引用計數法與可達性分析算法。

2.1 引用計數法(Reference Counting Collector)

該方法使用引用計數器來區分存活對象和不再使用的對象。一般來說,堆中的每個對象對應一個引用計數器。當每一次建立一個對象并賦給一個變量時,引用計數器置為1。當對象被賦給任意變量時,引用計數器每次加1,當對象出了作用域後(該對象丢棄不再使用),引用計數器減1,一旦引用計數器為0,對象就滿足了垃圾收集的條件。

引用記數法邏輯比較簡單,運作速度也比較快。但是它有一個緻命的缺點,無法解決循環引用問題。

例如,A引用B,B也引用A,它們處于互相引用的狀态。

?1234A a = new A(); B b = new B();a.ref = b;b.ref = a;

此時,A和B各被引用兩次。

?12a = nullb = null

這時我不再想使用這兩個對象,将變量引用置為null,此時,A和B的引用計數各減1。但是,它們還是各被引用了1次,是以垃圾回收器無法回收這兩個對象。

2.2 可達性分析算法

在主流的商用程式語言中(Java和C#),都是使用可達性分析算法判斷對象是否存活的。這個算法的基本思路就是通過一系列名為GC Roots的對象作為起始點,從這些節點開始向下搜尋,搜尋所走過的路徑稱為引用鍊(Reference Chain),當一個對象到GC Roots沒有任何引用鍊相連時,則證明此對象是不可用的,下圖對象object5, object6, object7雖然有互相判斷,但它們到GC Roots是不可達的,是以它們将會判定為是可回收對象。

那麼那些點可以作為GC Roots呢?一般來說,以下情況的對象可以作為GC Roots:

- 虛拟機棧(棧桢中的本地變量表)中的引用的對象

- 方法區中的類靜态屬性引用的對象

- 方法區中的常量引用的對象

- 本地方法棧中JNI(Native方法)的引用的對象

3. finalize方法

finalize是在回收一個對象之前會先調用finalize方法。但是這個調用時機是不确定的,并且在不同的jvm中調用時機也是不确定的,最後,它可能還不會被執行!是以,我們并不能依賴finalize方法做一些事情。

但是,finalize有什麼用呢?

釋放非java代碼建立的存儲空間

這種情況出現在使用“本地方法的時候(jni中)”,例如你可能調用C的malloc()函數來配置設定存儲空間,而且除非調用了free()函數,否則無法釋放該存儲空間,造成記憶體洩漏。

在這種時候就可以在finalize方法中再次調用本地方法釋放,雖然finalize調用的時機不可預料或者不被調用,但總比不釋放好。

本文由職坐标整理并釋出,希望對同學們有所幫助。了解更多詳情請關注職坐标移動開發之Android頻道!