java比較牛逼的地方就是垃圾回收機制,不用想C++那樣需要手動管理內存,那麼java自動管理內存,為啥還會出現內存洩漏嘞?
如何界定一個對象是否可以被回收?兩種方法,引用計數法,可達性分析法。
引用計數法:每個對象有一個引用計數屬性,新增一個該對象的引用時,計數+1,該對象的引用釋放時,計數-1,當計數為0時,說明可以回收。但是引用計數法無法解決相互引用問題,因為相互引用時計數為1,永遠無法被回收。
可達性分析法:從GC Roots開始向下搜索,所走過的路徑稱為引用連,當一個對象到GC Roots沒有任何引用鏈時,虛擬機判斷其為可回收對象。該方法可以解決循環引用問題。
內存洩漏:
內存洩露就是指一個不再被程序使用的對象或變量一直被佔據在內存中。也就是,有可能此對象已經不使用了,但是還有其它對象保持著此對象的引用,就會導致 GC 不能回收此對象,這種情況下就會出現內存洩漏。
來個內存洩漏的例子:
//此時,所有的Object對象都沒有被釋放,因為變量v引用這些對象。
//如果對象加入到 Vector 後,還必須從 Vector 中刪除,最簡單的方法就是將 Vector 對象設置為 null。
int times = 10; Vector vertor = new Vector<>(times); LongStream.rangeClosed(0, times).boxed().forEach(n -> { Object o = new Object(); vertor.add(o); o = null; });
循環申請 Object 對象,並將所申請的對象放入一個 Vector 中,如果我們僅僅釋放引用本身,那麼 Vector 仍然引用該對象,所以這個對象對 GC 來說是不可回收的。
最後總結下:
內存溢出 out of memory,是指程序在申請內存時,沒有足夠的內存空間供其使用,出現 out of memory。
內存洩露 memory leak,是指程序在申請內存後,無法釋放已申請的內存空間,一次內存洩露危害可以忽略,但內存洩露堆積後果很嚴重,無論多少內存,遲早會被佔光。
所以內存洩漏可能會導致內存溢出,但內存溢出並不完全都是因為內存洩漏,也有可能使用了太多的大對象導致。