oom和內(nèi)存泄露

### 1內(nèi)存溢出(out of memory):

通俗理解就是內(nèi)存不夠赦颇,通常在運(yùn)行大型軟件或游戲時(shí)二鳄,軟件或游戲所需要的內(nèi)存遠(yuǎn)遠(yuǎn)超出了你主機(jī)內(nèi)安裝的內(nèi)存所承受大小,就叫內(nèi)存溢出媒怯。

此時(shí)軟件或游戲就運(yùn)行不了订讼,系統(tǒng)會(huì)提示內(nèi)存溢出,有時(shí)候會(huì)自動(dòng)關(guān)閉軟件扇苞,重啟電腦或者軟件后釋放掉一部分內(nèi)存又可以正常運(yùn)行該軟件或游戲一段時(shí)間欺殿。

#### 內(nèi)存溢出現(xiàn)象:

#####(第一種) Out Of MemoryError: PermGenspace

發(fā)生這種問題的原意是程序中使用了大量的jar或class,使java虛擬機(jī)裝載類的空間不夠鳖敷,與PermanentGeneration space有關(guān)脖苏。

解決這類問題有以下兩種辦法:

(1)增加java虛擬機(jī)中的XX:PermSize和XX:MaxPermSize參數(shù)的大小,其中XX:PermSize是初始永久保存區(qū)域大小定踱,XX:MaxPermSize是最大永久保存區(qū)域大小棍潘。如針對tomcat6.0,在catalina.sh 或catalina.bat文件中一系列環(huán)境變量名說明結(jié)束處(大約在70行左右)增加一行: JAVA_OPTS=" -XX:PermSize=64M -XX:MaxPermSize=128m" 如果是windows服務(wù)器還可以在系統(tǒng)環(huán)境變量中設(shè)置崖媚。感覺用tomcat發(fā)布sprint+struts+hibernate架構(gòu)的程序時(shí)很容易發(fā)生這種內(nèi)存溢出錯(cuò)誤亦歉。使用上述方法,我成功解決了部署ssh項(xiàng)目的tomcat服務(wù)器經(jīng)常宕機(jī)的問題至扰。

![](https://upload-images.jianshu.io/upload_images/17812646-c9c56fa771e9972a?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

(2)清理應(yīng)用程序中web-inf/lib下的jar

如果tomcat部署了多個(gè)應(yīng)用鳍徽,很多應(yīng)用都使用了相同的jar,可以將共同的jar移到tomcat共同的lib下敢课,減少類的重復(fù)加載阶祭。這種方法是網(wǎng)上部分人推薦的,我沒試過直秆,但感覺減少不了太大的空間濒募,最靠譜的還是第一種方法。

#####(第二種)Out Of MemoryError:? Java heap space

發(fā)生這種問題的原因是java虛擬機(jī)創(chuàng)建的對象太多圾结,在進(jìn)行垃圾回收之間瑰剃,虛擬機(jī)分配的到堆內(nèi)存空間已經(jīng)用滿了,與Heap space有關(guān)筝野。解決這類問題有兩種思路:

(1)檢查程序晌姚,看是否有死循環(huán)或不必要地重復(fù)創(chuàng)建大量對象粤剧。

找到原因后,修改程序和算法挥唠。我以前寫一個(gè)使用K-Means文本聚類算法對幾萬條文本記錄(每條記錄的特征向量大約10來個(gè))進(jìn)行文本聚類時(shí)抵恋,由于程序細(xì)節(jié)上有問題,就導(dǎo)致了Java heap space的內(nèi)存溢出問題宝磨,后來通過修改程序得到了解決弧关。

(2)增加Java虛擬機(jī)中Xms(初始堆大小)和Xmx(最大堆大谢斤薄)參數(shù)的大小世囊。如:set JAVA_OPTS= -Xms256m -Xmx1024m

![](https://upload-images.jianshu.io/upload_images/17812646-5e5693afdbc80064?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

#####(第三種)Out Of MemoryError:unable tocreate new native thread

在java應(yīng)用中,有時(shí)候會(huì)出現(xiàn)這樣的錯(cuò)誤:OutOfMemoryError: unable to create new native thread.這種怪事是因?yàn)镴VM已經(jīng)被系統(tǒng)分配了大量的內(nèi)存(比如1.5G)窿祥,并且它至少要占用可用內(nèi)存的一半株憾。

######出現(xiàn)的原因

引起內(nèi)存溢出的原因有很多種,常見的有以下幾種:

? 1壁肋、內(nèi)存中加載的數(shù)據(jù)量過于龐大号胚,如一次從數(shù)據(jù)庫取出過多數(shù)據(jù);

? 2、集合類中有對對象的引用浸遗,使用完后未清空猫胁,使得JVM不能回收;

? 3、代碼中存在死循環(huán)或循環(huán)產(chǎn)生過多重復(fù)的對象實(shí)體;

? 4跛锌、使用的第三方軟件中的BUG;

? ????5弃秆、啟動(dòng)參數(shù)設(shè)定的過小;

###### 解決辦法:

第一步,就是修改JVM啟動(dòng)參數(shù)髓帽,直接增加內(nèi)存菠赚。

第二步,檢查錯(cuò)誤日志郑藏,查看"OutOfMemory"錯(cuò)誤前是否有其它異澈獠椋或錯(cuò)誤。

第三步必盖,安排有經(jīng)驗(yàn)的編程人員對代碼進(jìn)行走查和分析拌牲,找出可能發(fā)生內(nèi)存溢出的位置。

第四步歌粥,使用內(nèi)存查看工具動(dòng)態(tài)查看內(nèi)存使用情況塌忽。

## MAT檢查:

1、? 生成dump

2失驶、? 找出溢出源

■DominatorTree(支配樹):列出每個(gè)對象(Objectinstance)與其引用關(guān)系的樹狀結(jié)構(gòu)土居,還包含了占有多大內(nèi)存,所占百分比

■Histogram視圖(截圖里柱子那個(gè),邊上的是Dominator Tree ):列出每個(gè)class產(chǎn)生了多少個(gè)實(shí)例擦耀,以及占有多大內(nèi)存棉圈,所占百分比

■可以很容易找出站內(nèi)存最多的幾個(gè)類,根據(jù)Retained Heap排序埂奈,找出前幾個(gè)迄损。

■可以分不同的維度來查看類的Histogram視圖,Group by class账磺、Group by superclass、Group by class? loader痊远、Group by package

■只要有溢出垮抗,時(shí)間久了,溢出類的實(shí)例數(shù)量或者其占有的內(nèi)存會(huì)越來越多碧聪,排名也就越來越前冒版,通過多次對比不同時(shí)間點(diǎn)下的Histogram圖對比就能很容易把溢出類找出來。

3逞姿、定位溢出源

通過Pat通過Path to GC Roots或者M(jìn)erge Shortest Paths to GC Roots

###內(nèi)存泄漏

也稱作"存儲(chǔ)滲漏"辞嗡,用動(dòng)態(tài)存儲(chǔ)分配函數(shù)動(dòng)態(tài)開辟的空間,在使用完畢后未釋放滞造,結(jié)果導(dǎo)致一直占據(jù)該內(nèi)存單元续室。直到程序結(jié)束。

(其實(shí)說白了就是該內(nèi)存空間使用完畢之后未回收)即所謂內(nèi)存泄漏谒养。

內(nèi)存泄漏形象的比喻是"操作系統(tǒng)可提供給所有進(jìn)程的存儲(chǔ)空間正在被某個(gè)進(jìn)程榨干"挺狰,最終結(jié)果是程序運(yùn)行時(shí)間越長,占用存儲(chǔ)空間越來越多买窟,最終用盡全部存儲(chǔ)空間丰泊,整個(gè)系統(tǒng)崩潰。所以"內(nèi)存泄漏"是從操作系統(tǒng)的角度來看的始绍。這里的存儲(chǔ)空間并不是指物理內(nèi)存瞳购,而是指虛擬內(nèi)存大小,這個(gè)虛擬內(nèi)存大小取決于磁盤交換區(qū)設(shè)定的大小亏推。由程序申請的一塊內(nèi)存学赛,如果沒有任何一個(gè)指針指向它,那么這塊內(nèi)存就泄漏了径簿。

一般來說內(nèi)存泄漏有兩種情況罢屈。

#####(第一種情況) :

如在C/C++ 語言中的,在堆中的分配的內(nèi)存篇亭,在沒有將其釋放掉的時(shí)候缠捌,就將所有能訪問這塊內(nèi)存的方式都刪掉(如指針重新賦值);

#####(第二種情況):

則是在內(nèi)存對象明明已經(jīng)不需要的時(shí)候,還仍然保留著這塊內(nèi)存和它的訪問方式(引用)曼月。第一種情況谊却,在 Java 中已經(jīng)由于垃圾回收機(jī)制的引入,得到了很好的解決哑芹。所以炎辨, Java 中的內(nèi)存泄漏,主要指的是第二種情況聪姿。

內(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ā)性是相對的盟榴。對于特定的環(huán)境曹质,偶發(fā)性的也許就變成了常發(fā)性的葫隙。所以測試環(huán)境和測試方法對檢測內(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程序釋放了所有申請的內(nèi)存蝴韭。但是對于一個(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)存泄漏它更難被檢測到

![](https://upload-images.jianshu.io/upload_images/17812646-8fdf0c9503e8d205?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

實(shí)例解釋:在這個(gè)例子中陈哑,代碼棧中存在Vector 對象的引用 v 和 Object 對象的引用 o 。在 For 循環(huán)中伸眶,我們不斷的生成新的對象惊窖,然后將其添加到 Vector 對象中,之后將 o 引用置空赚抡。問題是當(dāng) o 引用被置空后爬坑,如果發(fā)生 GC,我們創(chuàng)建的 Object 對象是否能夠被 GC 回收呢涂臣?答案是否定的。因?yàn)椋?GC 在跟蹤代碼棧中的引用時(shí)售担,會(huì)發(fā)現(xiàn) v 引用赁遗,而繼續(xù)往下跟蹤,就會(huì)發(fā)現(xiàn) v 引用指向的內(nèi)存空間中又存在指向 Object 對象的引用族铆。也就是說盡管 o 引用已經(jīng)被置空岩四,但是 Object 對象仍然存在其他的引用,是可以被訪問到的哥攘,所以 GC 無法將其釋放掉剖煌。如果在此循環(huán)之后, Object 對象對程序已經(jīng)沒有任何作用逝淹,那么我們就認(rèn)為此 Java 程序發(fā)生了內(nèi)存泄漏耕姊。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市栅葡,隨后出現(xiàn)的幾起案子茉兰,更是在濱河造成了極大的恐慌,老刑警劉巖欣簇,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件规脸,死亡現(xiàn)場離奇詭異,居然都是意外死亡熊咽,警方通過查閱死者的電腦和手機(jī)莫鸭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來横殴,“玉大人被因,你說我怎么就攤上這事。” “怎么了氏身?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵巍棱,是天一觀的道長。 經(jīng)常有香客問我蛋欣,道長航徙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任陷虎,我火速辦了婚禮到踏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尚猿。我一直安慰自己窝稿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布凿掂。 她就那樣靜靜地躺著伴榔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪庄萎。 梳的紋絲不亂的頭發(fā)上踪少,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機(jī)與錄音糠涛,去河邊找鬼援奢。 笑死,一個(gè)胖子當(dāng)著我的面吹牛忍捡,可吹牛的內(nèi)容都是我干的集漾。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼砸脊,長吁一口氣:“原來是場噩夢啊……” “哼具篇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起脓规,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤栽连,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后侨舆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體秒紧,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年挨下,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了熔恢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,953評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡臭笆,死狀恐怖叙淌,靈堂內(nèi)的尸體忽然破棺而出秤掌,到底是詐尸還是另有隱情,我是刑警寧澤鹰霍,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布闻鉴,位于F島的核電站,受9級特大地震影響茂洒,放射性物質(zhì)發(fā)生泄漏孟岛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一督勺、第九天 我趴在偏房一處隱蔽的房頂上張望渠羞。 院中可真熱鬧,春花似錦智哀、人聲如沸次询。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽屯吊。三九已至,卻和暖如春摹菠,著一層夾襖步出監(jiān)牢的瞬間雌芽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工辨嗽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人淮腾。 一個(gè)月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓糟需,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谷朝。 傳聞我的和親對象是個(gè)殘疾皇子洲押,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容