內(nèi)存溢出的原因有哪些?怎么解決?
內(nèi)存溢出的原因有哪些?怎么解決?
內(nèi)存溢出 out of memory,是指程序在申請(qǐng)內(nèi)存時(shí),沒有足夠的內(nèi)存空間供其使用,出現(xiàn)out of memory;比如申請(qǐng)了一個(gè)integer,但給它存了long才能存下的數(shù),那就是內(nèi)存溢出。那么當(dāng)你遇到這種情況時(shí)該怎么辦呢?今天小編為大家整理了一些解決方法,下面我們一起來看看吧!
簡介
內(nèi)存泄漏是指你向系統(tǒng)申請(qǐng)分配內(nèi)存進(jìn)行使用(new),可是使用完了以后卻不歸還(delete),結(jié)果你申請(qǐng)到的那塊內(nèi)存你自己也不能再訪問(也許你把它的地址給弄丟了),而系統(tǒng)也不能再次將它分配給需要的程序。一個(gè)盤子用盡各種方法只能裝4個(gè)果子,你裝了5個(gè),結(jié)果掉倒地上不能吃了。這就是溢出!比方說棧,棧滿時(shí)再做進(jìn)棧必定產(chǎn)生空間溢出,叫上溢,棧空時(shí)再做退棧也產(chǎn)生空間溢出,稱為下溢。就是分配的內(nèi)存不足以放下數(shù)據(jù)項(xiàng)序列,稱為內(nèi)存溢出.
以發(fā)生的方式來分類,內(nèi)存泄漏可以分為4類:
1. 常發(fā)性內(nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼會(huì)被多次執(zhí)行到,每次被執(zhí)行的時(shí)候都會(huì)導(dǎo)致一塊內(nèi)存泄漏。
2. 偶發(fā)性內(nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼只有在某些特定環(huán)境或操作過程下才會(huì)發(fā)生。常發(fā)性和偶發(fā)性是相對(duì)的。對(duì)于特定的環(huán)境,偶發(fā)性的也許就變成了常發(fā)性的。所以測試環(huán)境和測試方法對(duì)檢測內(nèi)存泄漏至關(guān)重要。
3. 一次性內(nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼只會(huì)被執(zhí)行一次,或者由于算法上的缺陷,導(dǎo)致總會(huì)有一塊僅且一塊內(nèi)存發(fā)生泄漏。比如,在類的構(gòu)造函數(shù)中分配內(nèi)存,在析構(gòu)函數(shù)中卻沒有釋放該內(nèi)存,所以內(nèi)存泄漏只會(huì)發(fā)生一次。
4. 隱式內(nèi)存泄漏。程序在運(yùn)行過程中不停的分配內(nèi)存,但是直到結(jié)束的時(shí)候才釋放內(nèi)存。嚴(yán)格的說這里并沒有發(fā)生內(nèi)存泄漏,因?yàn)樽罱K程序釋放了所有申請(qǐng)的內(nèi)存。但是對(duì)于一個(gè)服務(wù)器程序,需要運(yùn)行幾天,幾周甚至幾個(gè)月,不及時(shí)釋放內(nèi)存也可能導(dǎo)致最終耗盡系統(tǒng)的所有內(nèi)存。所以,我們稱這類內(nèi)存泄漏為隱式內(nèi)存泄漏。
從用戶使用程序的角度來看,內(nèi)存泄漏本身不會(huì)產(chǎn)生什么危害,作為一般的用戶,根本感覺不到內(nèi)存泄漏的存在。真正有危害的是內(nèi)存泄漏的堆積,這會(huì)最終消耗盡系統(tǒng)所有的內(nèi)存。從這個(gè)角度來說,一次性內(nèi)存泄漏并沒有什么危害,因?yàn)樗粫?huì)堆積,而隱式內(nèi)存泄漏危害性則非常大,因?yàn)檩^之于常發(fā)性和偶發(fā)性內(nèi)存泄漏它更難被檢測到
內(nèi)存溢出的原因以及解決方法
引起內(nèi)存溢出的原因有很多種,小編列舉一下常見的有以下幾種:
1.內(nèi)存中加載的數(shù)據(jù)量過于龐大,如一次從數(shù)據(jù)庫取出過多數(shù)據(jù);
2.集合類中有對(duì)對(duì)象的引用,使用完后未清空,使得JVM不能回收;
3.代碼中存在死循環(huán)或循環(huán)產(chǎn)生過多重復(fù)的對(duì)象實(shí)體;
4.使用的第三方軟件中的BUG;
5.啟動(dòng)參數(shù)內(nèi)存值設(shè)定的過小
內(nèi)存溢出的解決方案:
第一步,修改JVM啟動(dòng)參數(shù),直接增加內(nèi)存。(-Xms,-Xmx參數(shù)一定不要忘記加。)
第二步,檢查錯(cuò)誤日志,查看“OutOfMemory”錯(cuò)誤前是否有其它異常或錯(cuò)誤。
第三步,對(duì)代碼進(jìn)行走查和分析,找出可能發(fā)生內(nèi)存溢出的位置。
重點(diǎn)排查以下幾點(diǎn):
1.檢查對(duì)數(shù)據(jù)庫查詢中,是否有一次獲得全部數(shù)據(jù)的查詢。一般來說,如果一次取十萬條記錄到內(nèi)存,就可能引起內(nèi)存溢出。這個(gè)問題比較隱蔽,在上線前,數(shù)據(jù)庫中數(shù)據(jù)較少,不容易出問題,上線后,數(shù)據(jù)庫中數(shù)據(jù)多了,一次查詢就有可能引起內(nèi)存溢出。因此對(duì)于數(shù)據(jù)庫查詢盡量采用分頁的方式查詢。
2.檢查代碼中是否有死循環(huán)或遞歸調(diào)用。
3.檢查是否有大循環(huán)重復(fù)產(chǎn)生新對(duì)象實(shí)體。
4.檢查對(duì)數(shù)據(jù)庫查詢中,是否有一次獲得全部數(shù)據(jù)的查詢。一般來說,如果一次取十萬條記錄到內(nèi)存,就可能引起內(nèi)存溢出。這個(gè)問題比較隱蔽,在上線前,數(shù)據(jù)庫中數(shù)據(jù)較少,不容易出問題,上線后,數(shù)據(jù)庫中數(shù)據(jù)多了,一次查詢就有可能引起內(nèi)存溢出。因此對(duì)于數(shù)據(jù)庫查詢盡量采用分頁的方式查詢。
5.檢查List、MAP等集合對(duì)象是否有使用完后,未清除的問題。List、MAP等集合對(duì)象會(huì)始終存有對(duì)對(duì)象的引用,使得這些對(duì)象不能被GC回收。
第四步,使用內(nèi)存查看工具動(dòng)態(tài)查看內(nèi)存使用情況。
擴(kuò)展資料
數(shù)據(jù)類型超過了計(jì)算機(jī)字長的界限就會(huì)出現(xiàn)數(shù)據(jù)溢出的情況。導(dǎo)致內(nèi)存溢出問題的原因有很多,比如:
(1) 使用非類型安全(non-type-safe)的語言如 C/C++ 等。
(2) 以不可靠的方式存取或者復(fù)制內(nèi)存緩沖區(qū)。
(3)編譯器設(shè)置的內(nèi)存緩沖區(qū)太靠近關(guān)鍵數(shù)據(jù)結(jié)構(gòu)。
因素分析
1.內(nèi)存溢出問題是 C 語言或者 C++ 語言所固有的缺陷,它們既不檢查數(shù)組邊界,又不檢查類型可靠性(type-safety)。眾所周知,用 C/C++ 語言開發(fā)的程序由于目標(biāo)代碼非常接近機(jī)器內(nèi)核,因而能夠直接訪問內(nèi)存和寄存器,這種特性大大提升了 C/C++ 語言代碼的性能。只要合理編碼,C/C++應(yīng)用程序在執(zhí)行效率上必然優(yōu)于其它高級(jí)語言。然而,C/C++ 語言導(dǎo)致內(nèi)存溢出問題的可能性也要大許多。其他語言也存在內(nèi)存溢出問題,但它往往不是程序員的失誤,而是應(yīng)用程序的運(yùn)行時(shí)環(huán)境出錯(cuò)所致。
2. 當(dāng)應(yīng)用程序讀取用戶(也可能是惡意攻擊者)數(shù)據(jù),試圖復(fù)制到應(yīng)用程序開辟的內(nèi)存緩沖區(qū)中,卻無法保證緩沖區(qū)的空間足夠時(shí)(換言之,假設(shè)代碼申請(qǐng)了 N 字節(jié)大小的內(nèi)存緩沖區(qū),隨后又向其中復(fù)制超過 N 字節(jié)的數(shù)據(jù))。內(nèi)存緩沖區(qū)就可能會(huì)溢出。想一想,如果你向 12 盎司的玻璃杯中倒入 16 盎司水,那么多出來的 4 盎司水怎么辦?當(dāng)然會(huì)滿到玻璃杯外面了!
3. 最重要的是,C/C++編譯器開辟的內(nèi)存緩沖區(qū)常常鄰近重要的數(shù)據(jù)結(jié)構(gòu)。假設(shè)某個(gè)函數(shù)的堆棧緊接在在內(nèi)存緩沖區(qū)后面時(shí),其中保存的函數(shù)返回地址就會(huì)與內(nèi)存緩沖區(qū)相鄰。此時(shí),惡意攻擊者就可以向內(nèi)存緩沖區(qū)復(fù)制大量數(shù)據(jù),從而使得內(nèi)存緩沖區(qū)溢出并覆蓋原先保存于堆棧中的函數(shù)返回地址。這樣,函數(shù)的返回地址就被攻擊者換成了他指定的數(shù)值;一旦函數(shù)調(diào)用完畢,就會(huì)繼續(xù)執(zhí)行“函數(shù)返回地址”處的代碼。非但如此,C++ 的某些其它數(shù)據(jù)結(jié)構(gòu),比如 v-table 、例外事件處理程序、函數(shù)指針等,也可能受到類似的攻擊。
好了今天小編的介紹就到這里了,希望對(duì)大家有所幫助!如果你喜歡記得分享給身邊的朋友哦!
相關(guān)文章: