JVM內存溢出和內存泄漏的區(qū)別及說明
1、概念的區(qū)分
1.1、 內存泄露(memory leak)
程序運行結束后,沒有釋放 所占用的內存空間。
一次內存泄漏 似乎不會有大的影響,但內存泄漏 不斷累積,最終可用內存會變得越來越少。
比如說,總內存大小是100 MB,有40MB的內存一直無法回收,那么可用的只有60MB 。這40MB的就是內存泄漏。
內存泄漏,就是程序運行結束后,沒有釋放的內存。
1.2、內存溢出(out of memory)
程序運行時,在申請內存空間時,沒有足夠的內存空間供其正常使用,程序運行停止,并拋出 out of memory 。
比如程序運行時申請了一個10MB 空間, 但是當前可用內存只有5MB,程序無法正常執(zhí)行,這就是內存溢出。
內存溢出 ,可以理解為程序運行需要的內存大于當前可用的內存。
1.3 舉例
(1)單例模式中,單例的生命周期和應用程序是一樣長的,所以單例程序中如果持有對外部對象的引用的話,那么這個外部對象是不能被回收的,則會導致 內存泄露 的產生。
(2)一些提供close的資源未閉導致 內存泄漏 。數據庫連接(dataSource.getConnection() ),網絡連接(socket)和 IO流的連接必須在finally中 close,否則不能被回收的。
(3)讀取大文件,一次讀取的文件大于可用內存,會導致 內存溢出 ??捎脙却媸?G,怎么讀取2G的文件呢?建一個100MB的字節(jié)數組,讀10次。
2、二者的區(qū)別和聯(lián)系
2.1 區(qū)別
內存泄露: 程序運行結束后,所占用的內存沒有全部釋放。
內存溢出:程序運行時,需要的內存大于當前可用的內存,內存不足,程序無法繼續(xù)執(zhí)行,拋出 “內存溢出”,程序運行中斷,結束。
2.2 聯(lián)系
一次 內存泄露 可能對程序運行沒有明顯的影響,多次 內存泄露 最終會導致 內存溢出 。
比如總內存大小是100MB,一次程序運行結束有,有10MB 沒有釋放,當前可用內存還有90MB,程序還可以運行。但是多次運行后, 可用內存 最終為0, 沒有可以內存或內存不足時,程序在下一次運行時,會因為內存不足,而出現 內存溢出 。
3、內存溢出的原因以及解決方法
3.1 內存溢出的原因
引起內存溢出的原因有很多種,小編列舉一下常見的有以下幾種:
- 內存中加載的數據量過于龐大,如一次從數據庫取出過多數據;
- 集合類中有對對象的引用,使用完后未清空,使得JVM不能回收;
- 代碼中存在死循環(huán)或循環(huán)產生過多重復的對象實體;
- 使用的第三方軟件中的BUG;啟動參數內存值設定的過小 。
3.2 內存溢出的解決方案
第一步,修改JVM啟動參數,直接增加內存。(-Xms、-Xmx 參數一定不要忘記加)
第二步,檢查錯誤日志,查看 “OutOfMemory” 錯誤前是否有其它異常或錯誤。
第三步,對代碼進行走查和分析,找出可能發(fā)生內存溢出的位置。
重點排查以下幾點:
1.檢查對數據庫查詢中,是否有一次獲得全部數據的查詢。
- 一般來說,如果一次取十萬條記錄到內存,就可能引起內存溢出。
- 這個問題比較隱蔽,在上線前,數據庫中數據較少,不容易出問題,上線后,
- 數據庫中數據多了,一次查詢就有可能引起內存溢出。因此對于數據庫查詢盡量采用分頁的方式查詢。
2.檢查代碼中是否有死循環(huán)或遞歸調用。
3.檢查是否有大循環(huán)重復產生新對象實體。
4.檢查對數據庫查詢中,是否有一次獲得全部數據的查詢。
- 一般來說,如果一次取十萬條記錄到內存,就可能引起內存溢出。
- 這個問題比較隱蔽,在上線前,數據庫中數據較少,不容易出問題,
- 上線后,數據庫中數據多了,一次查詢就有可能引起內存溢出。因此對于數據庫查詢盡量采用分頁的方式查詢。
5.檢查List、MAP等集合對象是否有使用完后,未清除的問題。
List、MAP等集合對象會始終存有對對象的引用,使得這些對象不能被GC回收。
第四步,使用內存查看工具動態(tài)查看內存使用情況。
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
SpringBoot中并發(fā)定時任務的實現、動態(tài)定時任務的實現(看這一篇就夠了)推薦
這篇文章主要介紹了SpringBoot并發(fā)定時任務動態(tài)定時任務實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-04-04Java中BeanUtils.copyProperties的11個坑總結
我們日常開發(fā)中,經常涉及到DO、DTO、VO對象屬性拷貝賦值,很容易想到org.springframework.beans.BeanUtils的copyProperties,它會自動通過反射機制獲取源對象和目標對象的屬性,pyProperties,會有好幾個坑呢,本文將給大家總結一下遇到的坑,需要的朋友可以參考下2023-05-05BeanUtils.copyProperties()所有的空值不復制問題
這篇文章主要介紹了BeanUtils.copyProperties()所有的空值不復制問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06Java?Thread.currentThread().getName()?和?this.getName()區(qū)別詳
本文主要介紹了Thread.currentThread().getName()?和?this.getName()區(qū)別詳解,TestThread?testThread?=?new?TestThread();2022-02-02使用XSD校驗Mybatis的SqlMapper配置文件的方法(1)
這篇文章以前面對SqlSessionFactoryBean的重構為基礎,簡單的介紹了相關操作知識,然后在給大家分享使用XSD校驗Mybatis的SqlMapper配置文件的方法,感興趣的朋友參考下吧2016-11-11springBoot的事件機制GenericApplicationListener用法解析
這篇文章主要介紹了springBoot的事件機制GenericApplicationListener用法解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值的相關資料2019-09-09如何使用@Slf4j和logback-spring.xml搭建日志框架
這篇文章主要介紹了如何使用@Slf4j和logback-spring.xml搭建日志框架問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06