真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

java中的內(nèi)存溢出與內(nèi)存泄漏是什么

內(nèi)存泄漏(Memory Leak)

成都創(chuàng)新互聯(lián)公司主營(yíng)達(dá)川網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,手機(jī)APP定制開發(fā),達(dá)川h5重慶小程序開發(fā)公司搭建,達(dá)川網(wǎng)站營(yíng)銷推廣歡迎達(dá)川等地區(qū)企業(yè)咨詢

概念

內(nèi)存泄漏(Memory Leak)是指程序中己動(dòng)態(tài)分配的堆內(nèi)存由于某種原因程序未釋放或無(wú)法釋放,造成系統(tǒng)內(nèi)存的浪費(fèi),導(dǎo)致程序運(yùn)行速度減慢甚至系統(tǒng)崩潰等嚴(yán)重后果。

 內(nèi)存泄漏缺陷具有隱蔽性、積累性的特征,比其他內(nèi)存非法訪問錯(cuò)誤更難檢測(cè)。因?yàn)閮?nèi)存泄漏的產(chǎn)生原因是內(nèi)存塊未被釋放,屬于遺漏型缺陷而不是過(guò)錯(cuò)型缺陷。此外,內(nèi)存泄漏通常不會(huì)直接產(chǎn)生可觀察的錯(cuò)誤癥狀,而是逐漸積累,降低系統(tǒng)整體性能,極端的情況下可能使系統(tǒng)崩潰。

發(fā)生條件

內(nèi)存泄漏必須滿足以下兩個(gè)條件

對(duì)象是可達(dá)的。即在有向圖中,存在通道達(dá)到該對(duì)象,GC不會(huì)回收

對(duì)象是無(wú)用的。即程序以后不會(huì)再使用該對(duì)象

發(fā)生場(chǎng)景

靜態(tài)集合類引起內(nèi)存泄漏

HashMap、Vactor等集合的使用最容易出現(xiàn)內(nèi)存泄漏。因?yàn)檫@些集合屬于靜態(tài)集合,這些靜態(tài)變量的生命周期和應(yīng)用程序一致,他們所引用的所有Object對(duì)象都不能被釋放,因?yàn)檫@些對(duì)象還一直被Vector引用著

Static Vector v = new Vector(10);

for (int i = 1; i<100; i++)

{

Object o = new Object(); //每次創(chuàng)建新的對(duì)象

v.add(o);

o = null; //將對(duì)象添加到集合后將對(duì)象的引用置空

}

//因?yàn)閷?duì)象的引用置空之后,JVM已經(jīng)失去的使用該對(duì)象的價(jià)值,本應(yīng)該被GC清除,但是在vector集合中還存在著此對(duì)象的引用,導(dǎo)致沒能順利清除

循環(huán)申請(qǐng)Object 對(duì)象,并將所申請(qǐng)的對(duì)象放入一個(gè)Vector 中,如果僅僅釋放引用本身(o=null),那么Vector 仍然引用該對(duì)象,所以這個(gè)對(duì)象對(duì)GC 來(lái)說(shuō)是不可回收的。因此,如果對(duì)象加入到Vector 后,還必須從Vector 中刪除,最簡(jiǎn)單的方法就是將v = null。這樣就可以將Vector執(zhí)行那個(gè)的對(duì)象也釋放。

當(dāng)集合(Hash算法的集合)里面的對(duì)象屬性被修改后,再調(diào)用remove()方法時(shí)不起作用

public static void main(String[] args) {

Set set = new HashSet();

Person p1 = new Person("唐僧", "pwd1", 25);

Person p2 = new Person("孫悟空", "pwd2", 26);

Person p3 = new Person("豬八戒", "pwd3", 27);

set.add(p1);

set.add(p2);

set.add(p3);

System.out.println("總共有:" + set.size() + " 個(gè)元素!"); //結(jié)果:總共有:3 個(gè)元素!

p3.setAge(2); //修改p3的年齡,此時(shí)p3元素對(duì)應(yīng)的hashcode值發(fā)生改變

set.remove(p3); //此時(shí)remove不掉,造成內(nèi)存泄漏

set.add(p3); //重新添加,居然添加成功

System.out.println("總共有:" + set.size() + " 個(gè)元素!"); //結(jié)果:總共有:4 個(gè)元素!

for (Person person : set) {

System.out.println(person);

System.out.println(person.hashCode());

}

}

監(jiān)聽器

在java 編程中,我們都需要和監(jiān)聽器打交道,通常一個(gè)應(yīng)用當(dāng)中會(huì)用到很多監(jiān)聽器,我們會(huì)調(diào)用一個(gè)控件的諸如addXXXListener()等方法來(lái)增加監(jiān)聽器,但往往在釋放對(duì)象的時(shí)候卻沒有記住去刪除這些監(jiān)聽器,從而增加了內(nèi)存泄漏的機(jī)會(huì)。

各種連接

比如數(shù)據(jù)庫(kù)連接(dataSourse.getConnection()),網(wǎng)絡(luò)連接(socket)和io連接,除非其顯式的調(diào)用了其close()方法將其連接關(guān)閉,否則是不會(huì)自動(dòng)被GC 回收的。對(duì)于Resultset 和Statement 對(duì)象可以不進(jìn)行顯式回收,但Connection 一定要顯式回收,因?yàn)镃onnection 在任何時(shí)候都無(wú)法自動(dòng)回收,而Connection一旦回收,Resultset 和Statement 對(duì)象就會(huì)立即為NULL。但是如果使用連接池,情況就不一樣了,除了要顯式地關(guān)閉連接,還必須顯式地關(guān)閉Resultset Statement 對(duì)象(關(guān)閉其中一個(gè),另外一個(gè)也會(huì)關(guān)閉),否則就會(huì)造成大量的Statement 對(duì)象無(wú)法釋放,從而引起內(nèi)存泄漏。這種情況下一般都會(huì)在try里面去的連接,在finally里面釋放連接。

單例模式

如果單例對(duì)象持有外部對(duì)象的引用,那么這個(gè)外部對(duì)象將不能被jvm正?;厥眨瑢?dǎo)致內(nèi)存泄露。

不正確使用單例模式是引起內(nèi)存泄露的一個(gè)常見問題,單例對(duì)象在被初始化后將在JVM的整個(gè)生命周期中存在(以靜態(tài)變量的方式),如果單例對(duì)象持有外部對(duì)象的引用,那么這個(gè)外部對(duì)象將不能被jvm正?;厥?,導(dǎo)致內(nèi)存泄露,考慮下面的例子:

class A {

public A() {

B.getInstance().setA(this);

}

....

}

//B類采用單例模式

class B {

private A a;

private static B instance = new B();

public B() {

}

public static B getInstance() {

return instance;

}

public void setA(A a) {

this.a = a;

}

//getter...

}

顯然B采用singleton模式,它持有一個(gè)A對(duì)象的引用,而這個(gè)A類的對(duì)象將不能被回收。想象下如果A是個(gè)比較復(fù)雜的對(duì)象或者集合類型會(huì)發(fā)生什么情況

分類鄭州婦科醫(yī)院 http://www.zyfuke.com/

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)境或操作過(guò)程下才會(huì)發(fā)生。常發(fā)性和偶發(fā)性是相對(duì)的。對(duì)于特定的環(huán)境,偶發(fā)性的也許就變成了常發(fā)性的。所以測(cè)試環(huán)境和測(cè)試方法對(duì)檢測(cè)內(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)行過(guò)程中不停的分配內(nèi)存,但是直到結(jié)束的時(shí)候才釋放內(nèi)存。嚴(yán)格的說(shuō)這里并沒有發(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)存溢出(Out Of Memory)

概念

程序在申請(qǐng)內(nèi)存時(shí),沒有足夠的內(nèi)存空間供其使用

 內(nèi)存溢出已經(jīng)是軟件開發(fā)歷史上存在了近40年的“老大難”問題,像在“紅色代碼”病毒事件中表現(xiàn)的那樣,它已經(jīng)成為黑客攻擊企業(yè)網(wǎng)絡(luò)的“罪魁禍?zhǔn)住薄?如在一個(gè)域中輸入的數(shù)據(jù)超過(guò)了它的要求就會(huì)引發(fā)數(shù)據(jù)溢出問題,多余的數(shù)據(jù)就可以作為指令在計(jì)算機(jī)上運(yùn)行。據(jù)有關(guān)安全小組稱,操作系統(tǒng)中超過(guò)50%的安全漏洞都是由內(nèi)存溢出引起的,其中大多數(shù)與微軟的技術(shù)有關(guān)。內(nèi)存溢出錯(cuò)誤是大數(shù)據(jù)處理平臺(tái)的常見錯(cuò)誤,例如,國(guó)際知名的程序開發(fā)者問答網(wǎng)站 stackoverflow 上關(guān)于“Hadoop out of memory”的問題超過(guò)10000個(gè),在Spark郵件列表上有10%的問題是關(guān)于“out of memory”。 內(nèi)存溢出錯(cuò)誤會(huì)導(dǎo)致處理數(shù)據(jù)的任務(wù)失敗,甚至?xí)l(fā)平臺(tái)崩潰等嚴(yán)重后果。對(duì)于內(nèi)存溢出大部分的處理方法是重新執(zhí)行任務(wù),然而, 對(duì)于由系統(tǒng)配置、數(shù)據(jù)流、用戶代碼等原因而導(dǎo)致的內(nèi)存溢出錯(cuò)誤,即使用戶重新執(zhí)行任務(wù)依然無(wú)法避免

發(fā)生條件

內(nèi)存中加載的數(shù)據(jù)過(guò)于龐大,如一次性從數(shù)據(jù)庫(kù)取出過(guò)多的數(shù)據(jù)

集合類中,有對(duì)對(duì)象的引用,使用完后未清空,使得JVM不能不嫩回收

代碼中存在死循環(huán)或循環(huán)產(chǎn)生過(guò)多重復(fù)的對(duì)象實(shí)體

使用的第三方軟件存在bug

啟動(dòng)參數(shù)內(nèi)存值設(shè)置的過(guò)小

分類

OutOfMemoryError: PermGen space

PermGen Space指的是內(nèi)存的永久保存區(qū),該塊內(nèi)存主要是被JVM用來(lái)存放class和meta信息的,當(dāng)class被加載loader的時(shí)候就會(huì)被存儲(chǔ)到該內(nèi)存區(qū)中,與存放類的實(shí)例的heap區(qū)不同,java中的垃圾回收器GC不會(huì)在主程序運(yùn)行期對(duì)PermGen space進(jìn)行清理。

因此,程序啟動(dòng)時(shí)如果需要加載的信息太多,超出這個(gè)空間的大小,則會(huì)發(fā)生溢出。

解決方案: 增加空間分配——增加java虛擬機(jī)中的XX:PermSize和XX:MaxPermSize參數(shù)的大小,其中XX:PermSize是初始永久保存區(qū)域大小,XX:MaxPermSize是最大永久保存區(qū)域大小。

OutOfMemoryError:Java heap space

heap space是Java內(nèi)存中的堆區(qū),主要用來(lái)存放對(duì)象,當(dāng)對(duì)象太多超出了空間大小,GC又來(lái)不及釋放的時(shí)候,就會(huì)發(fā)生溢出錯(cuò)誤。即內(nèi)存泄露越來(lái)越嚴(yán)重時(shí),可能會(huì)發(fā)生內(nèi)存溢出。

解決方案:(1)、檢查程序,減少大量重復(fù)創(chuàng)建對(duì)象的死循環(huán),減少內(nèi)存泄露。

(2)、增加Java虛擬機(jī)中Xms(初始堆大小)和Xmx(最大堆大小)參數(shù)的大小。

StackOverFlowError

stack是Java內(nèi)存中的棧空間,主要用來(lái)存放方法中的變量,參數(shù)等臨時(shí)性的數(shù)據(jù)的,發(fā)生溢出一般是因?yàn)榉峙淇臻g太小,或是執(zhí)行的方法遞歸層數(shù)太多創(chuàng)建了占用了太多棧幀導(dǎo)致溢出。

解決方案: 修改配置參數(shù)-Xss參數(shù)增加線程棧大小之外,優(yōu)化程序是尤其重要。

OOM排查思路

第一步,修改JVM啟動(dòng)參數(shù),直接增加內(nèi)存。(-Xms,-Xmx參數(shù)一定不要忘記加。)

第二步,檢查錯(cuò)誤日志,查看“OutOfMemery”錯(cuò)誤前,是否有其他異常或錯(cuò)誤

第三步,對(duì)代碼進(jìn)行走查分析,找出可能發(fā)生內(nèi)存溢出的位置

重點(diǎn)排查以下幾點(diǎn):

1.檢查對(duì)數(shù)據(jù)庫(kù)查詢中,是否有一次獲得全部數(shù)據(jù)的查詢。一般來(lái)說(shuō),如果一次取十萬(wàn)條記錄到內(nèi)存,就可能引起內(nèi)存溢出。這個(gè)問題比較隱蔽,在上線前,數(shù)據(jù)庫(kù)中數(shù)據(jù)較少,不容易出問題,上線后,數(shù)據(jù)庫(kù)中數(shù)據(jù)多了,一次查詢就有可能引起內(nèi)存溢出。因此對(duì)于數(shù)據(jù)庫(kù)查詢盡量采用分頁(yè)的方式查詢。

2.檢查代碼中是否有死循環(huán)或遞歸調(diào)用。

3.檢查是否有大循環(huán)重復(fù)產(chǎn)生新對(duì)象實(shí)體。

4.檢查L(zhǎng)ist、MAP等集合對(duì)象是否有使用完后,未清除的問題。List、MAP等集合對(duì)象會(huì)始終存有對(duì)對(duì)象的引用,使得這些對(duì)象不能被GC回收。

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


分享文章:java中的內(nèi)存溢出與內(nèi)存泄漏是什么
當(dāng)前鏈接:http://weahome.cn/article/pggjoh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部