Java內存回收機制
一、Java對象在內存引用狀態
內存泄露:程序運行過程中,會不斷分配內存空間,那些不再使用的內存空間應該即時回收它們,從而保證系統可以再次使用這些內存,如果存在無用的內存沒有被回收回來,這就是內存泄漏.
(1)強引用
這是java程序中最常見的引用方式,程序創建一個對象,并把這個對象賦給一個引用變量,這個引用變量就是強引用.java程序可通過強引用來訪問實際的對象。當一個對象被一個或一個以上的強引用變量引用時,它處于可達狀態,它不可能被系統垃圾回收機制回收。
強引用是Java編程中廣泛使用的引用類型,被強引用所引用的Java對象絕不會被垃圾回收機制回收,即使系統內存緊張;即使有些Java對象以后永遠也不會被用到,JVM也不會回收被強引用所引用的Java對象.
由于JVM肯定不會回收強引用所引用的JAVA對象,因此強引用是造成JAVA內存泄漏的主要原因。
如 ReceiptBean rb=new ReceiptBean(); rb就代表了一種強引用的方式
(2)軟引用
軟引用需要通過SoftReference類來實現,當一個對象只具有軟引用時,它可能被垃圾回收機制回收。對于只有軟引用的對象而言,當系統內存空間足夠時,它不會被系統回收,程序也可以使用該對象;當系統內存空間不足時,系統將回收它.
軟引用通常用在對內存敏感的程序中,軟引用是強引用很好的替代。對于軟引用,當系統內存空間充足時,軟引用與強引用沒有太大的區別,當系統內存空間不足時,被軟引用所引用的JAVA對象可以被垃圾回收機制回收,從而避免系統內存不足的異常.
當程序需要大量創建某個類的新對象,而且有可能重新訪問已創建老對象時,可以充分使用軟引用來解決內存緊張的問題。
例如需要訪問1000個Person對象,可以有兩種方式
方法一 依次創建1000個對象,但只有一個Person引用指向最后一個Person對象
方法二 定義一個長度為1000個的Person數組,每個數組元素引用一個Person對象.
對于方法一,弱點很明顯,程序不允許需要重新訪問前面創建的Person對象,即使這個對象所占的空間還沒有被回收。但已經失去了這個對象的引用,因此也不得不重新創建一個新的Person對象(重新分配內存),而那個已有的Person對象(完整的,正確的,可用的)則只能等待垃圾回收
對于方法二,優勢是可以隨時重新訪問前面創建的每個Person對象,但弱點也有,如果系統堆內存空間緊張,而1000個Person對象都被強引用引著,垃圾回收機制也不可能回收它們的堆內存空間,系統性能將變成非常差,甚至因此內存不足導致程序中止。
如果用軟引用則是一種較好的方案,當堆內存空間足夠時,垃圾回收機制不會回收Person對象,可以隨時重新訪問一個已有的Person對象,這和普通的強引用沒有任何區別。但當heap堆內存空間不足時,系統也可以回收軟引用引用的Person對象,從而提高程序運行性能,避免垃圾回收.
當程序使用強引用時,無論系統堆內存如何緊張,JVM垃圾回收機制都不會回收被強引用所引用的Java對象,因此最后導致程序因內存不足而中止。但如果把強引用改為軟引用,就完成可以避免這種情況,這就是軟引用的優勢所在.
(3)弱引用
弱引用與軟引用有點相似,區別在于弱引用所引用對象的生存期更短。弱引用通過WeakReference類實現,弱引用和軟引用很像,但弱引用的引用級別更低。對于只有弱引用的對象而言,當系統垃圾回收機制運行時,不管系統內存是否足夠,總會回收該對象所占用的內存。當然,并不是說當一個對象只有弱引用時,它就會立即被回收,正如那些失去引用的對象一樣,必須等到系統垃圾回收機制運行時才會被回收.
總結說明:
1.弱引用具有很大的不確定性,因為每次垃圾回收機制執行時都會回收弱引用所引用的對象,而垃圾回收機制的運行又不受程序員的控制,因此程序獲取弱引用所引用的java對象時必須小心空指針異常,通過弱引用所獲取的java對象可能是null
2.由于垃圾回收的不確定性,當程序希望從弱引用中取出被引用對象時,可能這個被引用對象已經被釋放了。如果程序需要使用被引用的對象,則必須重新創建該對象。
(4)虛引用
軟引用和弱引用可以單獨使用,但虛引用不能單獨使用,單獨使用虛引用沒有太大的意義。虛引用的主要作用就是跟蹤對象被垃圾回收的狀態,程序可以通過檢查虛引用關聯的引用隊列中是否包含指定的虛引用,從而了解虛引用所引用的對象是否將被回收.
引用隊列由java.lang.ref.ReferenceQueue類表示,它用于保存被回收對象的引用。當把軟引用,弱引用和引用隊列聯合使用時,系統回收被引用的對象之后,將會把被回收對象對應的引用添加到關聯的引用隊列中。與軟引用和弱引用不同的是,虛引用在對象被釋放之前,將把它對應的虛引用添加到關聯的隊列中,這使得可以在對象被回收之前采取行動。
虛引用通過PhantomReference類實現,它完全類似于沒有引用。虛引用對對象本身沒有大的影響,對象甚至感覺不到虛引用的存在。如果一個對象只有一個虛引用,那它和沒有引用的效果大致相同。虛引用主要用于跟蹤對象被垃圾回收的狀態,虛引用不能單獨使用,虛引用必須和隊列ReferenceQueue聯合使用.