Java中內存泄漏和內存溢出

內存泄漏:一個不再被程序使用的對象或變量還在內存中佔有存儲空間

【一次內存泄漏似乎不會有大的影響,但內存泄漏堆積的後果就是內存溢出】

內存溢出:指程序申請內存時,沒有足夠的內存供申請者使用,或者說,給了你一塊存儲int類型數據的存儲空間,但是你卻存儲long類型的數據,那麼結果就是內存不夠用,此時就會報錯OOM,即所謂的內存溢出。

二者的關係:

  1. 內存泄漏的堆積最終會導致內存溢出;
  2. 內存溢出就是你要的內存空間超過了系統實際分配給你的空間,此時系統相當於沒法滿足你的需求,就會報內存溢出的錯誤;
  3. 內存泄漏是指你向系統申請分配內存進行使用(new),可以使用完了以後卻不歸還,結果你申請到的那塊內存你自己也不能訪問(也需你把它的地址給弄丟了),而系統也不能再次將它分配給需要的程序。就相當於你租了個待鑰匙的櫃子,你存完東西之後吧櫃子鎖上之後,把鑰匙丟了或者沒有將鑰匙還回去,那麼結果就是這個櫃子將無法供給任何人使用,也無法被垃圾回收器回收,因爲找不到他的任何信息。
  4. 內存溢出:一個盤子用盡各種方法只能裝4個果子,你裝了5個,結果掉到地上不能吃了。這就是溢出。比方說棧,棧滿時再做進棧必定產生空間溢出,叫上溢出,棧空時再做退棧也產生空間溢出,稱爲下溢出。就是分配的內存不足以放下數據序列,稱爲內存溢出。說白了就是我承受不了那麼多,那我就報錯。

由於Java的JVM引入了垃圾回收機制,垃圾回收器會自動回收不再使用的對象,瞭解JVM回收機制的都知道JVM是使用引用計數器和可達性分析算法來判斷對象是否是不再使用對象,本質都是判斷一個對象是否還被引用。那麼對於這種情況下,由於代碼的實現不同就會出現很多種內存泄漏問題(讓JVM誤以爲此對象還在引用中,無法回收,造成內存泄漏)

 

造成內存泄漏的原因:

  1. 靜態集合類:如HashMap、LinkedList等等。如果這些容器爲靜態的,那麼它們的生命週期與程序一致,則容器中的對象在程序結束之前將不能被釋放,從而造成內存泄漏。簡單而言,長生命週期的對象持有短生命週期對象的引用,儘管短生命週期的對象不再使用,但是因爲長生命週期對象持有它的引用而導致不能回收。
  2. 各種連接:如數據庫連接,網絡連接和IO連接等。在數據庫進行曹鎖的過程中,首先需要建立與數據庫的連接,當不再使用時,需要調用close方法來釋放與數據庫的連接。只有連接被關閉後,垃圾回收器纔會回收對象的對象。否則,如果在訪問數據庫的過程中,對Connection、Statement或ResultSet不顯性地關閉,將會造成大量的對象無法被回收,從而引起內存泄漏。
  3. 變量不合理的作用域:一般而言,一個變量的定義的作用範圍大於其使用範圍,很有可能會造成內存泄漏。另一方面,如果沒有及時地把對象設置爲null,很有可能導致內存泄漏的發生。
  4. 內部類持有外部類:如果一個外部類的實例對象的方法返回了一個內部類的實例對象,這個內部類對象被長期引用了,即使那個外部類實例對象不再使用,但由於內部類持有外部類的實例對象,這個外部類對象將不會別垃圾回收,這也會造成內存泄漏。
  5. 改變哈希值:

當一個對象被存儲進HashSet集合中以後,就不能修改這個對象中的那些參與計算哈希值的字段了,否則,對象修改後的哈希值與最初存儲進HashSet集合中的哈希值就不同了,在這種情況下,即使在contains方法使用該對象的當前引用作爲的參數去HashSet集合中檢索對象,也將返回找不到對象的結果,這也會導致無法從HashSet集合中單獨刪除當前對象,造成內存泄漏。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章