JAVA中的內存溢出和內存泄露分別是什麼,有什麼聯繫和區別,讓咱們來看一看。緩存
01架構
內存泄漏 & 內存溢出ide
1.內存泄漏(memory leak )測試
申請了內存用完了不釋放,好比一共有 1024M 的內存,分配了 521M 的內存一直不回收,那麼能夠用的內存只有 521M 了,彷彿泄露掉了一部分;對象
通俗一點講的話,內存泄漏就是【佔着茅坑不拉shi】。blog
2.內存溢出(out of memory)生命週期
申請內存時,沒有足夠的內存可使用;內存
通俗一點兒講,一個廁所就三個坑,有兩個站着茅坑不走的(內存泄漏),剩下最後一個坑,廁所表示接待壓力很大,這時候一會兒來了兩我的,坑位(內存)就不夠了,內存泄漏變成內存溢出了。資源
可見,內存泄漏和內存溢出的關係:內存泄露的增多,最終會致使內存溢出。hash
這是一個頗有味道的例子。
如上圖:
對象 X 引用對象 Y,X 的生命週期比 Y 的生命週期長;
那麼當Y生命週期結束的時候,X依然引用着Y,這時候,垃圾回收期是不會回收對象Y的;
若是對象X還引用着生命週期比較短的A、B、C,對象A又引用着對象 a、b、c,這樣就可能形成大量無用的對象不能被回收,進而佔據了內存資源,形成內存泄漏,直到內存溢出。
02
泄漏的分類
·
常常發生:發生內存泄露的代碼會被屢次執行,每次執行,泄露一塊內存;
·
·
偶然發生:在某些特定狀況下才會發生;
·
·
一次性:發生內存泄露的方法只會執行一次;
·
·
隱式泄露:一直佔着內存不釋放,直到執行結束;嚴格的說這個不算內存泄露,由於最終釋放掉了,可是若是執行時間特別長,也可能會致使內存耗盡。
03
致使內存泄漏的常見緣由
循環過多或死循環,產生大量對象;
單例模式,和靜態集合致使內存泄露的緣由相似,由於單例的靜態特性,它的生命週期和 JVM 的生命週期同樣長,因此若是單例對象若是持有外部對象的引用,那麼這個外部對象也不會被回收,那麼就會形成內存泄漏。
數據鏈接、IO、Socket鏈接等等,它們必須顯示釋放(用代碼 close 掉),不然不會被 GC 回收。
內部類的對象被長期持有,那麼內部類對象所屬的外部類對象也不會被回收。
能夠看到,在測試方法中,當元素的 hashCode 發生改變以後,就再也找不到改變以前的那個元素了;
這也是 String 爲何被設置成了不可變類型,咱們能夠放心地把 String 存入 HashSet,或者把 String 當作 HashMap 的 key 值;
當咱們想把本身定義的類保存到散列表的時候,須要保證對象的 hashCode 不可變。
專一於Java架構師技術分享,撩我免費送Java全套架構師晉級資料
(Java架構師交流企Q鵝裙/:445-820-908 )