Java內(nèi)存泄露模擬及分析解決方法_第1頁
Java內(nèi)存泄露模擬及分析解決方法_第2頁
Java內(nèi)存泄露模擬及分析解決方法_第3頁
Java內(nèi)存泄露模擬及分析解決方法_第4頁
Java內(nèi)存泄露模擬及分析解決方法_第5頁
已閱讀5頁,還剩3頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、e-mail:derweeJava內(nèi)存泄露模擬及分析解決方法1.1實(shí)踐目標(biāo):1、使用JAVA代碼實(shí)現(xiàn)模擬內(nèi)存溢出2、分析JDK內(nèi)存溢出的原因3、總結(jié)存在bug的JAVA編碼實(shí)踐4、總結(jié)JVM優(yōu)化的方法1.2模擬內(nèi)存溢由:為了方便模擬內(nèi)存,特意把JVM的內(nèi)存參數(shù)指定為更小(我的本本內(nèi)存是8G的)。修改eclipse參數(shù)文件eclipse.ini調(diào)用JVM參數(shù):-vmargs-Xms40m(原始是-Xms40m)-Xmx100m(原始是-Xmx384m)演示JAVA小程序?qū)崿F(xiàn)原理:使用集合類對(duì)象裝載大量的Persion對(duì)象,每次把new出來的對(duì)象加入集合類對(duì)象后,更改對(duì)象的屬性,再從集合類對(duì)象中刪

2、除該對(duì)象。會(huì)出現(xiàn)該刪除的對(duì)象沒有被刪掉,Persion類對(duì)象不斷占用內(nèi)存,導(dǎo)致分配給JVM的內(nèi)存被耗光。package;importjava.util.*;/* ClassName:OutOfMemory* Description:內(nèi)存溢出模擬,提出解決方法* authoryangdw* date2012-3-25下午6:58:49*/publicclassOutOfMemorypublicstaticvoidmain(String口args)Collectioncollection=newHashSet();for(inti=0;i<0;i+)Persionper=newPersion

3、(i,"yangdw");collection.add(per);/把new出來的對(duì)象加到集合里去per.setName( "hundsun" collection.remove(per);/System.gc();/手工調(diào)用垃圾回收器"請(qǐng)注意,現(xiàn)在集合對(duì)有 persion對(duì)象數(shù)-"+collection.size();package ;/* ClassName : Persion* Description : TODO(這里用一句話描述這個(gè)類的作用)* author yangdw* date 2012 - 3-25 下午 8:16:

4、54*/publicclass Persion public Persion( int id, String name) super ();this. id = id;this. name = name;privateint id ;private String name;publicint getId() return id ; publicvoid setId( int id) this . id = id; public String getName() return name; publicvoid setName(String name) this . name = name;Ove

5、rridepublicint hashCode() finalint prime = 31;int result = 1;result = prime * result + |result = prime * result + (id ;namenull ) ? 0 :name .hashCode(););/把剛new出來的對(duì)象的名字改為hundsun/把剛加到集合里的對(duì)象刪除returnresult;Overridepublicbooleanequals(Objectobj)if(this=obj)returntrue;if(obj=null)returnfalse;if(getClass(

6、)!=obj.getClass()returnfalse;Persionother=(Persion)obj;if(id!=other.id)returnfalse;if(name=null)if(!=null)returnfalse;elseif(!name.equals()returnfalse;returntrue;使用JDK監(jiān)控程序進(jìn)行監(jiān)控JDK內(nèi)存,線程情況。模擬程序沒有運(yùn)行前的JDK內(nèi)存使用情況:運(yùn)行JAVA模擬程序后出現(xiàn):內(nèi)存溢出錯(cuò)誤:Exceptioninthread"main"Javaheapspaceatatata

7、tatJ.飛求澗冊(cè)牌itK6 *0ClassNaae:OutOfMaiiDry7 *SDescription;內(nèi)存益U榭拈鬼出飄方快8 *AuthorvariCTiwJO-W1f.r4j=y<v9 *Relate2工23-25下牛6不匕4910 */11 publicclassCctOfMejnory312publicstaticvoidmain(Strineargs)113臉:&Collectioncollection=newEashSet();116forfinti=0;i<&JGJOOOOO;i+)18Persicnper=newPersion(i,nyang

8、dw")心G011ecticn»add(p5r);。杷ne戲未版提力國集合里行per,setName("hurLdsiLr:'r);'杷剛樂壯來胸嘮的百?妒匕uEfin;:;:;:'VPsnrtV«Ay-eollseticn.renov(per;“明尷嘿言物掾制蓋|;2SysLex.our.println("港il,現(xiàn)磅自確pmrsicr濯矍泰-”+9ELmcticx.size();Problems®Javadoc庭院如此力日Cor汨日送、gErrorLegXa?®上*幽疝由周*OutO他emoiyJ

9、ay君AppLationjUptpgmntFjleNaraVdkl鼠)_29強(qiáng)琳araRac2012令25下午值都的J,國卻可在嘉合2推pg工/口鐮二25元5蒐4”Exceptioninthread"正:口”iva.Lang.OutGfManazyError;Javaheapspaceat:a¥-.ut-l.Ha£hMap.tJ£l£3(R+sLKap.W¥疝461*at-avp.utl,H3shMap»adiEntrY(HashNap.java:75Sianj.ut-l.HashNmp.put(HmshXag.j三ua:3

10、85xx3t-ava.iLtil.HaahEet,ad2(RmshS-t.己/己:2。3Husen.detKee,collection,menory.CutCfyem2ry.mainqCutCf-ejmrY.0:19)1.3內(nèi)存溢由原因分析:在JDK中內(nèi)存劃分主要分為堆和棧。堆主要存儲(chǔ)對(duì)象和數(shù)組;棧主要存儲(chǔ)JAVA原生類型變量。一般JDK初始化后棧占用大小變化不大。堆內(nèi)存是用戶使用的主要部分,大小變化很大,正常的占用圖應(yīng)該是波浪形的。-Xms:啟動(dòng)應(yīng)用時(shí),JVM堆空間的初始大小值。-Xmx:應(yīng)用運(yùn)行中,JVM堆空間的極限值。為了不消耗擴(kuò)大JVM堆控件分配的開銷,往往此參數(shù)和-Xms這個(gè)兩個(gè)值設(shè)

11、為相等。當(dāng)非堆內(nèi)存大小+堆內(nèi)存大小>JVM堆空間的極限值。就會(huì)出現(xiàn)Javaheapspace。解決方法:1、 評(píng)估應(yīng)用程序需要內(nèi)存大小。比如大量大對(duì)象存儲(chǔ)在集合對(duì)象內(nèi),遲遲不處理。應(yīng)該及時(shí)釋放稀有資源2、 釋放方式不合理,以為釋放了,其實(shí)沒有,如上面的演示程序。上面的演示程序中,因?yàn)槭褂昧艘詇ashcode來定位查找的hashset但對(duì)象的name參與計(jì)算hashcode的值被改變了,最后得到的hashcode變了,并沒有把該刪的對(duì)象刪除(collection.remove(per);把剛加到集合里的對(duì)象刪除),集合對(duì)象還引用著每一個(gè)剛新生成的對(duì)象,即使手工調(diào)用垃圾回收(System.g

12、c();手工調(diào)用垃圾回收器)也是沒有用的。因?yàn)槭止ふ{(diào)用gc方法僅僅是通知JVM而已,至于JVM垃圾回收線程有沒有空,能不能成功回收,gc也管不了。集合對(duì)象長度(collection.size()說明了內(nèi)存溢出。1.4 大型工程中內(nèi)存溢由排查建議1如果在大型工程里排查內(nèi)存溢出,Jconsole已經(jīng)不是最優(yōu)的工具了。因?yàn)镴console沒有提供細(xì)到對(duì)象級(jí)粒度的監(jiān)控。只能根據(jù)應(yīng)用程序正常狀態(tài)下耗用內(nèi)存量,和在異常狀態(tài)下耗用內(nèi)存量比較,可以明確是否存在內(nèi)存溢出的情況存在。如果已經(jīng)確定待處理的大型應(yīng)用程序存在內(nèi)存溢出問題,要定位到某個(gè)Java對(duì)象,某段Java邏輯代碼,位于某個(gè)Java文件,可以借助JP

13、r討iler進(jìn)行對(duì)象級(jí)的跟蹤,接著定位到相關(guān)邏輯代碼塊。如果這部分的工作給非常熟悉這個(gè)應(yīng)用程序的人排查,應(yīng)該可以比較快找出存在邏輯問題的代碼塊。1.5 存在bug的代碼實(shí)踐:其實(shí)造成內(nèi)存溢出,除了物理?xiàng)l件外,往往是代碼bug。上面實(shí)例是publicinthashCode()造成的內(nèi)存溢出,可見這個(gè)方法很神奇。在編寫代碼時(shí)往往重寫兩個(gè)方法hashCode和equals。hashCode:當(dāng)在集合類中如HashSet,HashMap,Hashtable中存儲(chǔ)對(duì)象時(shí),要特別注意hashCode的實(shí)現(xiàn),如果得到的哈希碼變了,在哈希集合中是無法定位該對(duì)象的,出現(xiàn)刪除該對(duì)象失敗的情況,最終導(dǎo)致了內(nèi)存溢出了

14、。equals:如果要比較對(duì)象的內(nèi)容,請(qǐng)重寫該方法,因?yàn)槟J(rèn)的,但String重寫了equals方法如:Setcompanys=newHashSet();companys.add(newStringBuffer("");companys.add(newStringBuffer(""注;/結(jié)果是2Setcompanys=newHashSet();companys.add(newString("");companys.add(newString("");/結(jié)果是1對(duì)于HashSet類是怎么確定一個(gè)對(duì)象是否已經(jīng)存在集合類

15、中呢?根據(jù)Java源碼,HashSet類首先看hashcode方法是否相等,然后看equals方法是否相等。注意:當(dāng)重寫對(duì)象的hashCode和equals,當(dāng)用到哈希集合時(shí)注意不要輕易更改參與哈希碼運(yùn)算的對(duì)象屬性,如person的id和name.1.5.1 equals和hashcode重寫原則 對(duì)equals()應(yīng)該遵循如下要求1) 對(duì)稱性:如果x.equals(y)返回是“true”,那么y.equals(x)也應(yīng)該返回是“true”。2) 自反性:x.equals(x)必須返回是“true”。3) 傳遞性:如果x.equals(y)返回是“true”,而且y.equal

16、s(z)返回是“true”,那么z.equals(x)也應(yīng)該返回是“true”。4) 任何情況下,x.equals(null),永遠(yuǎn)返回是“false”。5) x.equals(和x不同類型的對(duì)象)永遠(yuǎn)返回是“false”。 hashCode()的返回值和equals()的關(guān)系如下1) 如果x.equals(y)返回“true”,那么x和y的hashCode()必須相等。2) 如果x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。1.6基于JVM優(yōu)化開始使用JDK默認(rèn)參數(shù),使用JDK自帶的jconsole連續(xù)觀察內(nèi)存使用情況,線程

17、數(shù),確定基線后,設(shè)置合理的優(yōu)化參數(shù)。根據(jù)實(shí)際情況定制合適的優(yōu)化參數(shù),但不要盲目設(shè)置JVM的優(yōu)化參數(shù),可能會(huì)觸發(fā)JDK未知BUG!-Xms:啟動(dòng)應(yīng)用時(shí),JVM堆空間的初始大小值。-Xmx:應(yīng)用運(yùn)行中,JVM堆空間的極限值。為了不消耗擴(kuò)大JVM堆控件分配的開銷,往往此參數(shù)和-Xms這個(gè)兩個(gè)值設(shè)為相等。NewSize:堆中新對(duì)象區(qū)大小。PermSize設(shè)置非堆內(nèi)存初始值,默認(rèn)是物理內(nèi)存的1/64。MaxPermSize:應(yīng)用運(yùn)行中,永久存儲(chǔ)區(qū)的極限值。如:setJAVA_OPTS=-Xms800m-Xmx800m-XX:PermSize=128M-XX:MaxNewSize=256m-XX:MaxP

18、ermSize=256m優(yōu)化原則:1、在JVM中如果98的時(shí)間用于GC且可用的Heapsize不足2的時(shí)候?qū)伋龃水惓P畔ⅰ?、HeapSize最大不要超過可用物理內(nèi)存的80%,一般的要將-Xms和-Xmx選項(xiàng)設(shè)置為相同,而-Xmn為1/4的-Xmx值。3、 JVM初始分配的內(nèi)存由-Xms指定,默認(rèn)是物理內(nèi)存的1/64;JVM最大分配的內(nèi)存由-Xmx指定,默認(rèn)是物理內(nèi)存的1/4。4、 默認(rèn)空余堆內(nèi)存小于40%時(shí),JVM就會(huì)增大堆直到-Xmx的最大限制;空余堆內(nèi)存大于70%時(shí),JVM會(huì)減少堆直到-Xms的最小限制。因此服務(wù)器一般設(shè)置-Xms、-Xmx相等以避免在每次GC后調(diào)整堆的大小。5、內(nèi)存分配大小

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論