引用自:https://www.cnblogs.com/panxuejun/p/5883044.html
內(nèi)存溢出 out of memory酱塔,是指程序在申請內(nèi)存時(shí),沒有足夠的內(nèi)存空間供其使用,出現(xiàn)out of memory;
內(nèi)存泄露 memory leak,是指程序在申請內(nèi)存后音比,無法釋放已申請的內(nèi)存空間,一次內(nèi)存泄露危害可以忽略氢惋,但內(nèi)存泄露堆積后果很嚴(yán)重,無論多少內(nèi)存,遲早會被占光稽犁。
memory leak會最終會導(dǎo)致out of memory焰望!
以發(fā)生的方式來分類,內(nèi)存泄漏可以分為4類:?
1. 常發(fā)性內(nèi)存泄漏已亥。發(fā)生內(nèi)存泄漏的代碼會被多次執(zhí)行到熊赖,每次被執(zhí)行的時(shí)候都會導(dǎo)致一塊內(nèi)存泄漏。
2. 偶發(fā)性內(nèi)存泄漏虑椎。發(fā)生內(nèi)存泄漏的代碼只有在某些特定環(huán)境或操作過程下才會發(fā)生震鹉。常發(fā)性和偶發(fā)性是相對的。對于特定的環(huán)境捆姜,偶發(fā)性的也許就變成了常發(fā)性的传趾。所以測試環(huán)境和測試方法對檢測內(nèi)存泄漏至關(guān)重要。
3. 一次性內(nèi)存泄漏泥技。發(fā)生內(nèi)存泄漏的代碼只會被執(zhí)行一次浆兰,或者由于算法上的缺陷,導(dǎo)致總會有一塊僅且一塊內(nèi)存發(fā)生泄漏珊豹。比如簸呈,在類的構(gòu)造函數(shù)中分配內(nèi)存,在析構(gòu)函數(shù)中卻沒有釋放該內(nèi)存店茶,所以內(nèi)存泄漏只會發(fā)生一次蜕便。
4. 隱式內(nèi)存泄漏。程序在運(yùn)行過程中不停的分配內(nèi)存贩幻,但是直到結(jié)束的時(shí)候才釋放內(nèi)存轿腺。嚴(yán)格的說這里并沒有發(fā)生內(nèi)存泄漏,因?yàn)樽罱K程序釋放了所有申請的內(nèi)存丛楚。但是對于一個服務(wù)器程序吃溅,需要運(yùn)行幾天,幾周甚至幾個月鸯檬,不及時(shí)釋放內(nèi)存也可能導(dǎo)致最終耗盡系統(tǒng)的所有內(nèi)存决侈。所以,我們稱這類內(nèi)存泄漏為隱式內(nèi)存泄漏。
從用戶使用程序的角度來看赖歌,內(nèi)存泄漏本身不會產(chǎn)生什么危害枉圃,作為一般的用戶,根本感覺不到內(nèi)存泄漏的存在庐冯。真正有危害的是內(nèi)存泄漏的堆積孽亲,這會最終消耗盡系統(tǒng)所有的內(nèi)存。從這個角度來說展父,一次性內(nèi)存泄漏并沒有什么危害返劲,因?yàn)樗粫逊e,而隱式內(nèi)存泄漏危害性則非常大栖茉,因?yàn)檩^之于常發(fā)性和偶發(fā)性內(nèi)存泄漏它更難被檢測到
一篮绿、Java內(nèi)存回收機(jī)制?
不論哪種語言的內(nèi)存分配方式,都需要返回所分配內(nèi)存的真實(shí)地址吕漂,也就是返回一個指針到內(nèi)存塊的首地址亲配。Java中對象是采用new或者反射的方法創(chuàng)建的,這些對象的創(chuàng)建都是在堆(Heap)中分配的惶凝,所有對象的回收都是由Java虛擬機(jī)通過垃圾回收機(jī)制完成的吼虎。GC為了能夠正確釋放對象,會監(jiān)控每個對象的運(yùn)行狀況苍鲜,對他們的申請思灰、引用、被引用混滔、賦值等狀況進(jìn)行監(jiān)控官辈,Java會使用有向圖的方法進(jìn)行管理內(nèi)存,實(shí)時(shí)監(jiān)控對象是否可以達(dá)到遍坟,如果不可到達(dá)拳亿,則就將其回收,
二愿伴、Java內(nèi)存泄露引起原因?
內(nèi)存泄露是指無用對象(不再使用的對象)持續(xù)占有內(nèi)存或無用對象的內(nèi)存得不到及時(shí)釋放肺魁,從而造成的內(nèi)存空間的浪費(fèi)稱為內(nèi)存泄露。內(nèi)存泄露有時(shí)不嚴(yán)重且不易察覺隔节,這樣開發(fā)者就不知道存在內(nèi)存泄露鹅经,但有時(shí)也會很嚴(yán)重,會提示你Out of memory怎诫。
那么瘾晃,Java內(nèi)存泄露根本原因是什么呢?長生命周期的對象持有短生命周期對象的引用就很可能發(fā)生內(nèi)存泄露幻妓,盡管短生命周期對象已經(jīng)不再需要蹦误,但是因?yàn)殚L生命周期對象持有它的引用而導(dǎo)致不能被回收,這就是java中內(nèi)存泄露的發(fā)生場景。具體主要有如下幾大類:?