




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、Java基礎(chǔ)惡補內(nèi)存泄露、內(nèi)存溢出 (2010-09-15 15:56:26) 轉(zhuǎn)載標(biāo)簽:雜談要點內(nèi)存泄露是指程序中間動態(tài)分配了內(nèi)存,但在程序結(jié)束時沒有釋放這部分內(nèi)存,從而造成那部分內(nèi)存不可用的情況,重啟計算機可以解決,但也有可能再次發(fā)生內(nèi)存泄露,內(nèi)存泄露和硬件沒有關(guān)系,它是由軟件設(shè)計缺陷引起的。 內(nèi)存泄漏可以分為4類: 1) 常發(fā)性內(nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼會被多次執(zhí)行到,每次被執(zhí)行的時候都會導(dǎo)致一塊內(nèi)存泄漏。2) 偶發(fā)性內(nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼只有在某些特定環(huán)境或操作過程下才會發(fā)生。常發(fā)性和偶發(fā)性是相對的。對于特定的環(huán)境,偶發(fā)性的也許就變成了常發(fā)性的。所以測試環(huán)境和測試方法對檢測內(nèi)存
2、泄漏至關(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)存泄漏。程序在運行過程中不停的分配內(nèi)存,但是直到結(jié)束的時候才釋放內(nèi)存。嚴(yán)格的說這里并沒有發(fā)生內(nèi)存泄漏,因為最終程序釋放了所有申請的內(nèi)存。但是對于一個服務(wù)器程序,需要運行幾天,幾周甚至幾個月,不及時釋放內(nèi)存也可能導(dǎo)致最終耗盡系統(tǒng)的所有內(nèi)存。所以,我們稱這類內(nèi)存泄漏為隱式內(nèi)存泄漏。 內(nèi)存溢出類型:1) java.lang.OutOfMemoryError: PermGen
3、spacePermGen space 的全稱是 Permanent Generation space, 是指內(nèi)存的永久保存區(qū)域。這塊內(nèi)存主要是被JVM存放Class和Meta信息的,Class在被Loader時就會被放到PermGen space中,它和存放類實例(Instance)的Heap區(qū)域不同,GC不會在主程序運行期對PermGen space進行清理。JVM由XX:PermSize設(shè)置非堆內(nèi)存初始值,默認是物理內(nèi)存的1/64; JVM由XX:MaxPermSize設(shè)置最大非堆內(nèi)存的大小,默認是物理內(nèi)存的1/4。該錯誤常見場合:a) 應(yīng)用中有很多Class,web服務(wù)器對JSP進行pr
4、e compile時。 b) Webapp下用了大量的第三方j(luò)ar, 其大小超過了JVM默認的大小(4M)時。2) java.lang.OutOfMemoryError: Java heap space在JVM中如果98%的時間是用于GC且可用的Heap size 不足2%的時候?qū)伋龃水惓P畔?。JVM初始分配的內(nèi)存由-Xms指定,默認是物理內(nèi)存的1/64; JVM最大分配的內(nèi)存由-Xmx指定,默認是物理內(nèi)存的1/4。JVM內(nèi)存的最大值跟操作系統(tǒng)有很大的關(guān)系。32位處理器雖然可控內(nèi)存空間有4GB,但是具體的操作系統(tǒng)會給一個限制,這個限制一般是2GB-3GB(一般來說Windows系統(tǒng)下為1.5
5、G-2G,Linux系統(tǒng)下為2G-3G),而64bit以上的處理器就不會有限制了。注意:如果Xms超過了Xmx值,或者堆最大值和非堆最大值的總和超過了物理內(nèi)存或者操作系統(tǒng)的最大限制都會引起服務(wù)器啟動不起來。 該錯誤常見場合:a) Web上傳文件時。b) 開啟大型文件或從數(shù)據(jù)庫中一次取了太多的數(shù)據(jù)。相關(guān)問題 1. Q: Java中會存在內(nèi)存泄漏嗎?A: Java中也存在內(nèi)存泄露。當(dāng)被分配的對象可達但已無用(未對作廢數(shù)據(jù)內(nèi)存單元的引用置null)即會引起。如:Java代碼1. Vector v=new Vector(10);2. for (int i=1;i100; i ) 3. Object o
6、=new Object();4. v.add(o);5. o=null;6. 7. / 此時,所有的Object對象都沒有被釋放,因為變量v引用這些對象。8. / 對象加入到Vector后,還必須從Vector中刪除,最簡單釋放方法就是將Vector對象設(shè)置為null。2. Q: 內(nèi)存泄露、溢出的異同?A: 同:都會導(dǎo)致應(yīng)用程序運行出現(xiàn)問題,性能下降或掛起。異:1) 內(nèi)存泄露是導(dǎo)致內(nèi)存溢出的原因之一;內(nèi)存泄露積累起來將導(dǎo)致內(nèi)存溢出。2) 內(nèi)存泄露可以通過完善代碼來避免;內(nèi)存溢出可以通過調(diào)整配置來減少發(fā)生頻率,但無法徹底避免。3. 如何檢測內(nèi)存泄露?A: 可以通過一些性能監(jiān)測分析工具,如 JPr
7、ofiler、Optimizeit Profiler。4. Q: 如何避免內(nèi)存泄露、溢出?A: 1) 盡早釋放無用對象的引用。好的辦法是使用臨時變量的時候,讓引用變量在退出活動域后自動設(shè)置為null,暗示垃圾收集器來收集該對象,防止發(fā)生內(nèi)存泄露。 2) 程序進行字符串處理時,盡量避免使用String,而應(yīng)使用StringBuffer。因為每一個String對象都會獨立占用內(nèi)存一塊區(qū)域,如:Java代碼1. String str = aaa;2. String str2 = bbb;3. String str3 = str str2;4. / 假如執(zhí)行此次之后str , str2再不被調(diào)用,那么
8、它們就會在內(nèi)存中等待GC回收;5. / 假如程序中存在過多的類似情況就會出現(xiàn)內(nèi)存錯誤;3) 盡量少用靜態(tài)變量。因為靜態(tài)變量是全局的,GC不會回收。4) 避免集中創(chuàng)建對象尤其是大對象,如果可以的話盡量使用流操作。 JVM會突然需要大量內(nèi)存,這時會觸發(fā)GC優(yōu)化系統(tǒng)內(nèi)存環(huán)境; 一個案例如下:Java代碼1. / 使用jspsmartUpload作文件上傳,運行過程中經(jīng)常出現(xiàn)java.outofMemoryError的錯誤,2. / 檢查之后發(fā)現(xiàn)問題:組件里的代碼3. m_totalBytes = m_request.getContentLength();4. m_binArray = new byt
9、em_totalBytes;5. / totalBytes這個變量得到的數(shù)極大,導(dǎo)致該數(shù)組分配了很多內(nèi)存空間,而且該數(shù)組不能及時釋放。6. / 解決辦法只能換一種更合適的辦法,至少是不會引發(fā)outofMemoryError的方式解決。7. / 參考:5) 盡量運用對象池技術(shù)以提高系統(tǒng)性能。生命周期長的對象擁有生命周期短的對象時容易引發(fā)內(nèi)存泄漏,例如大集合對象擁有大數(shù)據(jù)量的業(yè)務(wù)對象的時候,可以考慮分塊進行處理,然后解決一塊釋放一塊的策略。 6) 不要在經(jīng)常調(diào)用的方法中創(chuàng)建對象,尤其是忌諱在循環(huán)中創(chuàng)建對象。可以適當(dāng)?shù)氖褂胔ashtable,vector 創(chuàng)建一組對象容器,然后從容器中去取那些對象,
10、而不用每次new之后又丟棄。7) 優(yōu)化配置。5. Q: 內(nèi)存溢出的解決方案?A: 一是從代碼層面進行優(yōu)化完善,盡量避免該情況發(fā)生;二是調(diào)整優(yōu)化服務(wù)器配置:1) 設(shè)置-Xms、-Xmx相等;2) 設(shè)置NewSize、MaxNewSize相等;3) 設(shè)置Heap size, PermGen space:在“echo Using CATALINA_BASE: $CATALINA_BASE”上面加入以下行:Cmd代碼1. set JAVA_OPTS=-Xms800m -Xmx800m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m-
11、/ 內(nèi)存泄露與溢出區(qū)別,何時產(chǎn)生內(nèi)存泄露?文章分類:Java編程內(nèi)存溢出是由于jvm虛擬內(nèi)存不夠!而泄漏則是另種概念!1下面實在摘抄的內(nèi)容!下面,我們就可以描述什么是內(nèi)存泄漏。在Java中,內(nèi)存泄漏就是存在一些被分配的對象,這些對象有下面兩個特點,首先,這些對象是可達的,即在有向圖中,存在通路可以與其相連;其次,這些對象是無用的,即程序以后不會再使用這些對象。如果對象滿足這兩個條件,這些對象就可以判定為Java中的內(nèi)存泄漏,這些對象不會被GC所回收,然而它卻占用內(nèi)存。在C+中,內(nèi)存泄漏的范圍更大一些。有些對象被分配了內(nèi)存空間,然后卻不可達,由于C+中沒有GC,這些內(nèi)存將永遠收不回來。在Java
12、中,這些不可達的對象都由GC負責(zé)回收,因此程序員不需要考慮這部分的內(nèi)存泄露。通過分析,我們得知,對于C+,程序員需要自己管理邊和頂點,而對于Java程序員只需要管理邊就可以了(不需要管理頂點的釋放)。通過這種方式,Java提高了編程的效率。因此,通過以上分析,我們知道在Java中也有內(nèi)存泄漏,但范圍比C+要小一些。因為Java從語言上保證,任何對象都是可達的,所有的不可達對象都由GC管理。對于程序員來說,GC基本是透明的,不可見的。雖然,我們只有幾個函數(shù)可以訪問GC,例如運行GC的函數(shù)System.gc(),但是根據(jù)Java語言規(guī)范定義, 該函數(shù)不保證JVM的垃圾收集器一定會執(zhí)行。因為,不同的
13、JVM實現(xiàn)者可能使用不同的算法管理GC。通常,GC的線程的優(yōu)先級別較低。JVM調(diào)用GC的策略也有很多種,有的是內(nèi)存使用到達一定程度時,GC才開始工作,也有定時執(zhí)行的,有的是平緩執(zhí)行GC,有的是中斷式執(zhí)行GC。但通常來說,我們不需要關(guān)心這些。除非在一些特定的場合,GC的執(zhí)行影響應(yīng)用程序的性能,例如對于基于Web的實時系統(tǒng),如網(wǎng)絡(luò)游戲等,用戶不希望GC突然中斷應(yīng)用程序執(zhí)行而進行垃圾回收,那么我們需要調(diào)整GC的參數(shù),讓GC能夠通過平緩的方式釋放內(nèi)存,例如將垃圾回收分解為一系列的小步驟執(zhí)行,Sun提供的HotSpot JVM就支持這一特性。下面給出了一個簡單的內(nèi)存泄露的例子。在這個例子中,我們循環(huán)申請
14、Object對象,并將所申請的對象放入一個Vector中,如果我們僅僅釋放引用本身,那么Vector仍然引用該對象,所以這個對象對GC來說是不可回收的。因此,如果對象加入到Vector后,還必須從Vector中刪除,最簡單的方法就是將Vector對象設(shè)置為null。Java代碼1. Vector v=new Vector(10);2. for (int i=1;i100; i+)3. 4. Object o=new Object();5. v.add(o);6. o=null;7. /此時,所有的Object對象都沒有被釋放,因為變量v引用這些對象怎樣解決內(nèi)存溢出一、內(nèi)存溢出類型1、java.
15、lang.OutOfMemoryError: PermGen spaceJVM管理兩種類型的內(nèi)存,堆和非堆。堆是給開發(fā)人員用的上面說的就是,是在JVM啟動時創(chuàng)建;非堆是留給JVM自己用的,用來存放類的信息的。它和堆不同,運行期內(nèi)GC不會釋放空間。如果web app用了大量的第三方j(luò)ar或者應(yīng)用有太多的class文件而恰好MaxPermSize設(shè)置較小,超出了也會導(dǎo)致這塊內(nèi)存的占用過多造成溢出,或者tomcat熱部署時侯不會清理前面加載的環(huán)境,只會將context更改為新部署的,非堆存的內(nèi)容就會越來越多。PermGen space的全稱是Permanent Generation space,是指
16、內(nèi)存的永久保存區(qū)域,這塊內(nèi)存主要是被JVM存放Class和Meta信息的,Class在被Loader時就會被放到PermGen space中,它和存放類實例(Instance)的Heap區(qū)域不同,GC(Garbage Collection)不會在主程序運行期對PermGen space進行清理,所以如果你的應(yīng)用中有很CLASS的話,就很可能出現(xiàn)PermGen space錯誤,這種錯誤常見在web服務(wù)器對JSP進行pre compile的時候。如果你的WEB APP下都用了大量的第三方j(luò)ar, 其大小超過了jvm默認的大小(4M)那么就會產(chǎn)生此錯誤信息了。一個最佳的配置例子:(經(jīng)過本人驗證,自從
17、用此配置之后,再未出現(xiàn)過tomcat死掉的情況)set JAVA_OPTS=-Xms800m -Xmx800m -XX:PermSize=128M-XX:MaxNewSize=256m -XX:MaxPermSize=256m2、java.lang.OutOfMemoryError: Javaheap space第一種情況是個補充,主要存在問題就是出現(xiàn)在這個情況中。其默認空間(即-Xms)是物理內(nèi)存的1/64,最大空間(-Xmx)是物理內(nèi)存的1/4。如果內(nèi)存剩余不到40%,JVM就會增大堆到Xmx設(shè)置的值,內(nèi)存剩余超過70%,JVM就會減小堆到Xms設(shè)置的值。所以服務(wù)器的Xmx和Xms設(shè)置一般
18、應(yīng)該設(shè)置相同避免每次GC后都要調(diào)整虛擬機堆的大小。假設(shè)物理內(nèi)存無限大,那么JVM內(nèi)存的最大值跟操作系統(tǒng)有關(guān),一般32位機是1.5g到3g之間,而64位的就不會有限制了。注意:如果Xms超過了Xmx值,或者堆最大值和非堆最大值的總和超過了物理內(nèi)存或者操作系統(tǒng)的最大限制都會引起服務(wù)器啟動不起來。垃圾回收GC的角色JVM調(diào)用GC的頻度還是很高的,主要兩種情況下進行垃圾回收:當(dāng)應(yīng)用程序線程空閑;另一個是java內(nèi)存堆不足時,會不斷調(diào)用GC,若連續(xù)回收都解決不了內(nèi)存堆不足的問題時,就會報out of memory錯誤。因為這個異常根據(jù)系統(tǒng)運行環(huán)境決定,所以無法預(yù)期它何時出現(xiàn)。根據(jù)GC的機制,程序的運行會
19、引起系統(tǒng)運行環(huán)境的變化,增加GC的觸發(fā)機會。為了避免這些問題,程序的設(shè)計和編寫就應(yīng)避免垃圾對象的內(nèi)存占用和GC的開銷。顯示調(diào)用System.GC()只能建議JVM需要在內(nèi)存中對垃圾對象進行回收,但不是必須馬上回收,一個是并不能解決內(nèi)存資源耗空的局面,另外也會增加GC的消耗。二、JVM內(nèi)存區(qū)域組成簡單的說java中的堆和棧java把內(nèi)存分兩種:一種是棧內(nèi)存,另一種是堆內(nèi)存1。在函數(shù)中定義的基本類型變量和對象的引用變量都在函數(shù)的棧內(nèi)存中分配;2。堆內(nèi)存用來存放由new創(chuàng)建的對象和數(shù)組在函數(shù)(代碼塊)中定義一個變量時,java就在棧中為這個變量分配內(nèi)存空間,當(dāng)超過變量的作用域后,java會自動釋放掉
20、為該變量所分配的內(nèi)存空間;在堆中分配的內(nèi)存由java虛擬機的自動垃圾回收器來管理堆的優(yōu)勢是可以動態(tài)分配內(nèi)存大小,生存期也不必事先告訴編譯器,因為它是在運行時動態(tài)分配內(nèi)存的。缺點就是要在運行時動態(tài)分配內(nèi)存,存取速度較慢; 棧的優(yōu)勢是存取速度比堆要快,缺點是存在棧中的數(shù)據(jù)大小與生存期必須是確定的無靈活性。java堆分為三個區(qū):New、Old和PermanentGC有兩個線程:新創(chuàng)建的對象被分配到New區(qū),當(dāng)該區(qū)被填滿時會被GC輔助線程移到Old區(qū),當(dāng)Old區(qū)也填滿了會觸發(fā)GC主線程遍歷堆內(nèi)存里的所有對象。Old區(qū)的大小等于Xmx減去-Xmnjava棧存放棧調(diào)整:參數(shù)有+UseDefaultStac
21、kSize -Xss256K,表示每個線程可申請256k的??臻g每個線程都有他自己的Stack三、JVM如何設(shè)置虛擬內(nèi)存提示:在JVM中如果98%的時間是用于GC且可用的Heap size 不足2%的時候?qū)伋龃水惓P畔?。提示:Heap Size 最大不要超過可用物理內(nèi)存的80%,一般的要將-Xms和-Xmx選項設(shè)置為相同,而-Xmn為1/4的-Xmx值。提示:JVM初始分配的內(nèi)存由-Xms指定,默認是物理內(nèi)存的1/64;JVM最大分配的內(nèi)存由-Xmx指定,默認是物理內(nèi)存的1/4。默認空余堆內(nèi)存小于40%時,JVM就會增大堆直到-Xmx的最大限制;空余堆內(nèi)存大于70%時,JVM會減少堆直到-X
22、ms的最小限制。因此服務(wù)器一般設(shè)置-Xms、-Xmx相等以避免在每次GC 后調(diào)整堆的大小。提示:假設(shè)物理內(nèi)存無限大的話,JVM內(nèi)存的最大值跟操作系統(tǒng)有很大的關(guān)系。簡單的說就32位處理器雖然可控內(nèi)存空間有4GB,但是具體的操作系統(tǒng)會給一個限制,這個限制一般是2GB-3GB(一般來說Windows系統(tǒng)下為1.5G-2G,Linux系統(tǒng)下為2G-3G),而64bit以上的處理器就不會有限制了提示:注意:如果Xms超過了Xmx值,或者堆最大值和非堆最大值的總和超過了物理內(nèi)存或者操作系統(tǒng)的最大限制都會引起服務(wù)器啟動不起來。提示:設(shè)置NewSize、MaxNewSize相等,new的大小最好不要大于old
23、的一半,原因是old區(qū)如果不夠大會頻繁的觸發(fā)主 GC ,大大降低了性能 JVM使用-XX:PermSize設(shè)置非堆內(nèi)存初始值,默認是物理內(nèi)存的1/64; 由XX:MaxPermSize設(shè)置最大非堆內(nèi)存的大小,默認是物理內(nèi)存的1/4。 解決方法:手動設(shè)置Heap size在“echo Using CATALINA_BASE: $CATALINA_BASE”上面加入以下行: JAVA_OPTS=-server -Xms800m -Xmx800m -XX:MaxNewSize=256m四、性能檢查工具使用定位內(nèi)存泄漏:JProfiler工具主要用于檢查和跟蹤系統(tǒng)(限于Java開發(fā)的)的性能。JPro
24、filer可以通過時時的監(jiān)控系統(tǒng)的內(nèi)存使用情況,隨時監(jiān)視垃圾回收,線程運行狀況等手段,從而很好的監(jiān)視JVM運行情況及其性能。1. 應(yīng)用服務(wù)器內(nèi)存長期不合理占用,內(nèi)存經(jīng)常處于高位占用,很難回收到低位;2. 應(yīng)用服務(wù)器極為不穩(wěn)定,幾乎每兩天重新啟動一次,有時甚至每天重新啟動一次;3. 應(yīng)用服務(wù)器經(jīng)常做Full GC(Garbage Collection),而且時間很長,大約需要30-40秒,應(yīng)用服務(wù)器在做Full GC的時候是不響應(yīng)客戶的交易請求的,非常影響系統(tǒng)性能。因為開發(fā)環(huán)境和產(chǎn)品環(huán)境會有不同,導(dǎo)致該問題發(fā)生有時會在產(chǎn)品環(huán)境中發(fā)生,通常可以使用工具跟蹤系統(tǒng)的內(nèi)存使用情況,在有些個別情況下或許某個時刻確實是使用了大量內(nèi)存導(dǎo)致out of memory,這時應(yīng)繼續(xù)跟蹤看接下來是否會有下降,如果一直居高不下這肯定就因為程序的原因?qū)е聝?nèi)存泄漏。五、不健壯代碼的特征及解決辦法1、盡早釋放無用對象的引用。好的辦法是使用臨時變量的時候,讓引用變量在退出活動域后,自動設(shè)置為null,暗示垃圾收集器來收集該對象,防止發(fā)生內(nèi)存泄露。對于仍然有指針指向的實例,jvm就不會回收該資源,因為垃圾回收會將值為null的對象作為垃圾,提高GC回收機制效率;2、我們的程序里不可避免大量使用字符串處理,避免使用String,應(yīng)大量使用StringBuffer,每一個String對象都得獨立
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 高等教育普及化背景下高職學(xué)生學(xué)習(xí)動機影響因素研究
- mcn公司簽約合同范例
- 青海橡膠圍堰施工方案
- 二手人防車位買賣合同范例
- 內(nèi)貿(mào)合同范例
- 2025年其它新型計算機外圍設(shè)備項目發(fā)展計劃
- 基于可靠度的光伏發(fā)電系統(tǒng)運維策略研究
- 冷庫運營外包合同范本
- 企業(yè)借款個人合同范例
- 買房欠債寫合同范例
- 15J403-1-樓梯欄桿欄板(一)
- DL∕T 5210.4-2018 電力建設(shè)施工質(zhì)量驗收規(guī)程 第4部分:熱工儀表及控制裝置
- 水利水電工程單元工程施工質(zhì)量驗收評定表及填表說明
- MOOC 數(shù)據(jù)庫系統(tǒng)(上):模型與語言-哈爾濱工業(yè)大學(xué) 中國大學(xué)慕課答案
- 導(dǎo)熱油使用操作規(guī)程
- 感受態(tài)細胞的制備(DH5α大腸桿菌)
- 中油即時通信安裝手冊(二廠)
- 分度頭的使用(課堂PPT)
- Reach REX錄播服務(wù)器CF系列技術(shù)白皮書V
- 玄靈玉皇寶經(jīng)
- 二年級下冊科學(xué)第二課磁鐵怎樣吸引物體ppt課件
評論
0/150
提交評論