第一篇:性能測試總結(jié)之內(nèi)存泄露和內(nèi)存溢出
性能測試總結(jié)之內(nèi)存泄露和內(nèi)存溢出
2009-12-10 作者:yunshuai 來源:Taobao QA Team
剛剛做完了一個項目的性能測試,“有幸”也遇到了內(nèi)存泄露的案例,所以在此和大家分享一下。
主要從以下幾部分來說明,關(guān)于內(nèi)存和內(nèi)存泄露、溢出的概念,區(qū)分內(nèi)存泄露和內(nèi)存溢出;內(nèi)存的區(qū)域劃分,了解GC回收機制;重點關(guān)注如何去監(jiān)控內(nèi)存問題;此外分析出問題還要如何解決內(nèi)存問題。下面就開始本篇的內(nèi)容: 第一部分 概念
眾所周知,java中的內(nèi)存java虛擬機自己去管理的,他不想C++需要自己去釋放。籠統(tǒng)地去講,java的內(nèi)存分配分為兩個部分,一個是數(shù)據(jù)堆,一個是序在運行的時候一般分配數(shù)據(jù)堆,把局部的臨時的變量都放進去,生命周期和進程有關(guān)系。但是如果程序員聲明了static的變量,就直接在棧中運行的,進了,不一定會銷毀static變量。
另外為了保證java內(nèi)存不會溢出,java中有垃圾回收機制。System.gc()即垃圾收集機制是指jvm用于釋放那些不再使用的對象所占用的內(nèi)存。java語言求jvm有g(shù)c,也沒有規(guī)定gc如何工作。垃圾收集的目的在于清除不再使用的對象。gc通過確定對象是否被活動對象引用來確定是否收集該對象。而其中,內(nèi)存溢出就是你要求分配的java虛擬機內(nèi)存超出了系統(tǒng)能給你的,系統(tǒng)不能滿足需求,于是產(chǎn)生溢出。
內(nèi)存泄漏是指你向系統(tǒng)申請分配內(nèi)存進行使用(new),可是使用完了以后卻不歸還(delete),結(jié)果你申請到的那塊內(nèi)存你自己也不能再訪問,該塊已分配出存也無法再使用,隨著服務(wù)器內(nèi)存的不斷消耗,而無法使用的內(nèi)存越來越多,系統(tǒng)也不能再次將它分配給需要的程序,產(chǎn)生泄露。一直下去,程序也逐漸使用,就會溢出。第二部分 原理
JAVA垃圾回收及對內(nèi)存區(qū)劃分
在Java虛擬機規(guī)范中,提及了如下幾種類型的內(nèi)存空間: ◇ 棧內(nèi)存(Stack):每個線程私有的。◇ 堆內(nèi)存(Heap):所有線程公用的。
◇ 方法區(qū)(Method Area):有點像以前常說的“進程代碼段”,這里面存放了每個加載類的反射信息、類函數(shù)的代碼、編譯時常量等信息。◇ 原生方法棧(Native Method Stack):主要用于JNI中的原生代碼,平時很少涉及。
而Java的使用的是堆內(nèi)存,java堆是一個運行時數(shù)據(jù)區(qū),類的實例(對象)從中分配空間。Java虛擬機(JVM)的堆中儲存著正在運行的應(yīng)用程序所建立的象,“垃圾回收”也是主要是和堆內(nèi)存(Heap)有關(guān)。
垃圾回收的概念就是JAVA虛擬機(JVM)回收那些不再被引用的對象內(nèi)存的過程。一般我們認為正在被引用的對象狀態(tài)為“alive”,而沒有被應(yīng)用或者取用屬性的對象狀態(tài)為“dead”。垃圾回收是一個釋放處于”dead”狀態(tài)的對象的內(nèi)存的過程。而垃圾回收的規(guī)則和算法被動態(tài)的作用于應(yīng)用運行當中,自動回JVM的垃圾回收器采用的是一種分代(generational)回收策略,用較高的頻率對年輕的對象(young generation)進行掃描和回收,這種叫做minor collec對老對象(old generation)的檢查回收頻率要低很多,稱為major collection。這樣就不需要每次GC都將內(nèi)存中所有對象都檢查一遍,這種策略有利于實時觀收。
(Sun JVM 1.3 有兩種最基本的內(nèi)存收集方式:一種稱為copying或scavenge,將所有仍然生存的對象搬到另外一塊內(nèi)存后,整塊內(nèi)存就可回收。這種效率,但需要有一定的空閑內(nèi)存,拷貝也有開銷。這種方法用于minor collection。另外一種稱為mark-compact,將活著的對象標記出來,然后搬遷到一起塊的內(nèi)存,其他內(nèi)存就可以回收了。這種方法不需要占用額外的空間,但速度相對慢一些。這種方法用于major collection.)一些對象被創(chuàng)建出來只是擁有短暫的生命周期,比如 iterators 和本地變量。另外一些對象被創(chuàng)建是擁有很長的生命周期,比如 高持久化對象等。
垃圾回收器的分代策略是把內(nèi)存區(qū)劃分為幾個代,然后為每個代分配一到多個內(nèi)存區(qū)塊。當其中一個代用完了分配給他的內(nèi)存后,JVM會在分配的內(nèi)存行一個局部的GC(也可以叫minor collection)操作,為了回收處于“dead”狀態(tài)的對象所占用的內(nèi)存。局部GC通常要不Full GC要快很多。
JVM定義了兩個代,年輕代(yong generation)(有時稱為“nursery”托兒所)和老年代(old generation)。年輕代包括 “Eden space(伊甸園)”和兩個“survivor虛擬內(nèi)存初始化的時候會把所有對象都分配到 Eden space,并且大部分對象也會在該區(qū)域被釋放。當進行 minor GC的時候,VM會把剩下的沒有釋放的Eden space移動到其中一個survivor spaces當中。此外,VM也會把那些長期存活在survivor spaces 里的對象移動到 老生代的“tenured” space中。當 tenured g被填滿后,就會產(chǎn)生Full GC,F(xiàn)ull GC會相對比較慢因為回收的內(nèi)容包括了所有的 live狀態(tài)的對象。pemanet generation這個代包括了所有java虛擬機自身相對比較穩(wěn)定的數(shù)據(jù)對象,比如類和對象方法等。關(guān)于代的劃分,可以從下圖中獲得一個概況:
如果垃圾回收器影響了系統(tǒng)的性能,或者成為系統(tǒng)的瓶頸,你可以通過自定義各個代的大小來優(yōu)化它的性能。使用JConsole,可以方便的查看到當前應(yīng)置的垃圾回收器的各個參數(shù)。想要獲得更詳細的參數(shù),可以參考以下調(diào)優(yōu)介紹: Tuning Garbage collection with the 5.0 HotSpot VM http://java.sun.com/docs/hotspot/gc/index.html 最后,總結(jié)一下各區(qū)內(nèi)存:
Eden Space(heap): 內(nèi)存最初從這個線程池分配給大部分對象。
Survivor Space(heap):用于保存在eden space內(nèi)存池中經(jīng)過垃圾回收后沒有被回收的對象。Tenured Generation(heap):用于保持已經(jīng)在 survivor space內(nèi)存池中存在了一段時間的對象。
Permanent Generation(non-heap): 保存虛擬機自己的靜態(tài)(refective)數(shù)據(jù),例如類(class)和方法(method)對象。Java虛擬機共享這些類數(shù)據(jù)。這個區(qū)割為只讀的和只寫的,Code Cache(non-heap):HotSpot Java虛擬機包括一個用于編譯和保存本地代碼(native code)的內(nèi)存,叫做“代碼緩存區(qū)”(code cache)第三部分 監(jiān)控(工具發(fā)現(xiàn)問題)
談到內(nèi)存監(jiān)控工具,JConsole是必須要介紹的,它是一個用JAVA寫的GUI程序,用來監(jiān)控VM,并可監(jiān)控遠程的VM,易用且功能強大。具體可監(jiān)控內(nèi)存、JAVA CPU使用率、線程執(zhí)行情況、加載類概況等,Jconsole需要在JVM參數(shù)中配置端口才能使用。由于是GUI程序,界面可視化,這里就不做詳細介紹,具體幫助支持文檔請參閱性能測試JConsole使用方法總結(jié):
http:// http://Java.sun.com/javase/6/docs/technotes/tools/share/jconsole.html
在實際測試某一個項目時,內(nèi)存出現(xiàn)泄露現(xiàn)象。起初在性能測試的1個小時中,并不明顯,而在穩(wěn)定性測試的時候才發(fā)現(xiàn),應(yīng)用的HSF調(diào)用在經(jīng)過幾個行后,就出現(xiàn)性能明顯下降的情況。在服務(wù)日志中報大量HSF超時,但所調(diào)用系統(tǒng)沒有任何超時日志,并且壓力應(yīng)用的load都很低。經(jīng)過查看日志后,認可能存在內(nèi)存泄漏。通過jconsole 以及 jmap 工具進行分析發(fā)現(xiàn),確實存在內(nèi)存泄漏問題,其中PS Old Gen最終達到占用 100%的占用。如圖所示:
從上圖可以看到,雖然每次Full GC,JVM內(nèi)存會有部分回收,但回收并不徹底,不可回收的內(nèi)存對象會越來越多,這樣便會出現(xiàn)以上的一個趨勢。在無法回收的對象越來越多時,最終已使用內(nèi)存達到系統(tǒng)分配的內(nèi)存最大值,系統(tǒng)最后無內(nèi)存可分配,最終down機。第四部分 分析
經(jīng)過開發(fā)和架構(gòu)師對應(yīng)用的分析,查看此時內(nèi)存隊列,看哪個對象占用數(shù)據(jù)最多,再利用jmap命令,對線程數(shù)據(jù)分析,如下所示: num #instances #bytes class name ———————————————-1: 9248056 665860032 com.taobao.matrix.mc.domain.** 2: 9248031 295936992 com.taobao.matrix.** 3: 9248068 147969088 java.util.** 4: 1542111 37010664 java.util.Date 前三個instances不斷增加,指代的是同一個代碼邏輯,異步分發(fā)的問題,堵塞消息,回收多次都無法回收成功。導(dǎo)致內(nèi)存溢出。此外,對應(yīng)用的性能單獨做了壓測,他的性能只能支撐到一半左右,故發(fā)送消息的TPS,應(yīng)用肯定無法處理過來,導(dǎo)致消息堆積,而JAVA垃圾回收期些都是有用的對象,導(dǎo)致內(nèi)存堆積,直至系統(tǒng)崩潰。
調(diào)優(yōu)方法
由于具體調(diào)優(yōu)方法涉及到應(yīng)用的配置信息,故在此暫不列出,可以參考性能測試小組發(fā)布的《性能測試調(diào)優(yōu)寶典》 第四部分 總結(jié)
內(nèi)存溢出主要是由于代碼編寫時對某些方法、類應(yīng)用不合理,或者沒有預(yù)估到臨時對象會占用很大內(nèi)存量,或者把過多的數(shù)據(jù)放入JVM緩存,或者性大導(dǎo)致消息堆積而占用內(nèi)存,以至于在性能測試時,生成龐大數(shù)量的臨時對象,GC時沒有做出有效回收甚至根本就不能回收,造成內(nèi)存空間不足,內(nèi)存如果編碼之前,對內(nèi)存使用量進行預(yù)估,對放在內(nèi)存中的數(shù)據(jù)進行評估,保證有用的信息盡快釋放,無用的信息能夠被GC回收,這樣在一定程度上是免內(nèi)存溢出問題的。
第二篇:性能測試總結(jié)之內(nèi)存泄露和內(nèi)存溢出
性能測試總結(jié)之內(nèi)存泄露和內(nèi)存溢出
主要從以下幾部分來說明,關(guān)于內(nèi)存和內(nèi)存泄露、溢出的概念,區(qū)分內(nèi)存泄露和內(nèi)存溢出;內(nèi)存的區(qū)域劃分,了解GC回收機制;重點關(guān)注如何去監(jiān)控和發(fā)現(xiàn)內(nèi)存問題;此外分析出問題還要如何解決內(nèi)存問題。
下面就開始本篇的內(nèi)容:
第一部分 概念
眾所周知,java中的內(nèi)存java虛擬機自己去管理的,他不想C++需要自己去釋放。籠統(tǒng)地去 講,java的內(nèi)存分配分為兩個部分,一個是數(shù)據(jù)堆,一個是棧。程序在運行的時候一般分配數(shù)據(jù)堆,把局部的臨時的變量都放進去,生命周期和進程有關(guān)系。但 是如果程序員聲明了static的變量,就直接在棧中運行的,進程銷毀了,不一定會銷毀static變量。
另外為了保證java內(nèi)存不會溢出,java中有垃圾回收機制。System.gc()即垃圾收集機制是指jvm用于釋放那些不再使用的對象所占用的內(nèi)存。java語言并不要求jvm有g(shù)c,也沒有規(guī)定gc如何工作。垃圾收集的目的在于清除不再使用的對象。gc通過確定對象是否被活動對象引用來確定是否收集該對象。
而其中,內(nèi)存溢出就是你要求分配的java虛擬機內(nèi)存超出了系統(tǒng)能給你的,系統(tǒng)不能滿足需求,于是產(chǎn)生溢出。
內(nèi)存泄漏是指你向系統(tǒng)申請分配內(nèi)存進行使用(new),可是使用完了以后卻不歸還(delete),結(jié)果你申請到的那塊內(nèi)存你自己也不能再訪問,該塊已分配出來的內(nèi)存也無法再使用,隨著服務(wù)器內(nèi)存的不斷消耗,而無法使用的內(nèi)存越來越 多,系統(tǒng)也不能再次將它分配給需要的程序,產(chǎn)生泄露。一直下去,程序也逐漸無內(nèi)存使用,就會溢出。
第二部分 原理
JAVA垃圾回收及對內(nèi)存區(qū)劃分
在Java虛擬機規(guī)范中,提及了如下幾種類型的內(nèi)存空間:
◇ 棧內(nèi)存(Stack):每個線程私有的。
◇ 堆內(nèi)存(Heap):所有線程公用的。
◇ 方法區(qū)(Method Area):有點像以前常說的“進程代碼段”,這里面存放了每個加載類的反射信息、類函數(shù)的代碼、編譯時常量等信息。
◇ 原生方法棧(Native Method Stack):主要用于JNI中的原生代碼,平時很少涉及。
而Java的使用的是堆內(nèi)存,java堆是一個運行時數(shù)據(jù)區(qū),類的實例(對象)從中分配空間。Java虛擬機(JVM)的堆中儲存著正在運行的應(yīng)用程序所建立的所有對象,“垃圾回收”也是主要是和堆內(nèi)存(Heap)有關(guān)。
垃圾回收的概念就是JAVA虛擬機(JVM)回收那些不再被引用的對象內(nèi)存的過程。一般我們認為正在被引用的對象狀態(tài)為“alive”,而沒有 被應(yīng)用或者取不到引用屬性的對象狀態(tài)為“dead”。垃圾回收是一個釋放處于”dead”狀態(tài)的對象的內(nèi)存的過程。而垃圾回收的規(guī)則和算法被動態(tài)的作用于 應(yīng)用運行當中,自動回收。
JVM的垃圾回收器采用的是一種分代(generational)回收策略,用較高的頻率對年輕的對象(young generation)進行掃描和回收,這種叫做minor collection,而對老對象(old generation)的檢查回收頻率要低很多,稱為major collection。這樣就不需要每次GC都將內(nèi)存中所有對象都檢查一遍,這種策略有利于實時觀察和回收。
(Sun JVM 1.3 有兩種最基本的內(nèi)存收集方式:一種稱為copying或scavenge,將所有仍然生存的對象搬到另外一塊內(nèi)存后,整塊內(nèi)存就可回收。這種方法有效率,但需要有一定的空閑內(nèi)存,拷貝也有開銷。這種方法用于minor collection。另外一種稱為mark-compact,將活著的對象標記出來,然后搬遷到一起連成大塊的內(nèi)存,其他內(nèi)存就可以回收了。這種方法不 需要占用額外的空間,但速度相對慢一些。這種方法用于major collection.)
一些對象被創(chuàng)建出來只是擁有短暫的生命周期,比如 iterators 和本地變量。
另外一些對象被創(chuàng)建是擁有很長的生命周期,比如 高持久化對象等。
垃圾回收器的分代策略是把內(nèi)存區(qū)劃分為幾個代,然后為每個代分配一到多個內(nèi)存區(qū)塊。當其中一個代用完了分配給他的內(nèi)存后,JVM會在分配的內(nèi)存 區(qū)內(nèi)執(zhí)行一個局部的GC(也可以叫minor collection)操作,為了回收處于“dead”狀態(tài)的對象所占用的內(nèi)存。局部GC通常要不Full GC要快很多。
JVM定義了兩個代,年輕代(yong generation)(有時稱為“nursery”托兒所)和老年代(old generation)。年輕代包括 “Eden space(伊甸園)”和兩個“survivor spaces”。虛擬內(nèi)存初始化的時候會把所有對象都分配到 Eden space,并且大部分對象也會在該區(qū)域被釋放。當進行 minor GC的時候,VM會把剩下的沒有釋放的對象從Eden space移動到其中一個survivor spaces當中。此外,VM也會把那些長期存活在survivor spaces 里的對象移動到 老生代的“tenured” space中。當 tenured generation 被填滿后,就會產(chǎn)生Full GC,F(xiàn)ull GC會相對比較慢因為回收的內(nèi)容包括了所有的 live狀態(tài)的對象。pemanet generation這個代包括了所有java虛擬機自身使用的相對比較穩(wěn)定的數(shù)據(jù)對象,比如類和對象方法等。
關(guān)于代的劃分,可以從下圖中獲得一個概況:
如果垃圾回收器影響了系統(tǒng)的性能,或者成為系統(tǒng)的瓶頸,你可以通過自定義各個代的大小來優(yōu)化它的性能。使用JConsole,可以方便的查看到當前應(yīng)用所配置的垃圾回收器的各個參數(shù)。想要獲得更詳細的參數(shù),可以參考以下調(diào)優(yōu)介紹:
Tuning Garbage collection with the 5.0 HotSpot VM
http://java.sun.com/docs/hotspot/gc/index.html
最后,總結(jié)一下各區(qū)內(nèi)存:
Eden Space(heap): 內(nèi)存最初從這個線程池分配給大部分對象。
Survivor Space(heap):用于保存在eden space內(nèi)存池中經(jīng)過垃圾回收后沒有被回收的對象。
Tenured Generation(heap):用于保持已經(jīng)在 survivor space內(nèi)存池中存在了一段時間的對象。
Permanent Generation(non-heap): 保存虛擬機自己的靜態(tài)(refective)數(shù)據(jù),例如類(class)和方法(method)對象。Java虛擬機共享這些類數(shù)據(jù)。這個區(qū)域被分割為只讀的和只寫的,Code Cache(non-heap):HotSpot Java虛擬機包括一個用于編譯和保存本地代碼(native code)的內(nèi)存,叫做“代碼緩存區(qū)”(code cache)
第三部分 監(jiān)控(工具發(fā)現(xiàn)問題)
談到內(nèi)存監(jiān)控工具,JConsole是必須要介紹的,它是一個用JAVA寫的GUI程序,用來監(jiān)控 VM,并可監(jiān)控遠程的VM,易用且功能強大。具體可監(jiān)控JAVA內(nèi)存、JAVA CPU使用率、線程執(zhí)行情況、加載類概況等,Jconsole需要在JVM參數(shù)中配置端口才能使用。
由于是GUI程序,界面可視化,這里就不做詳細介紹,具體幫助支持文檔請參閱性能測試JConsole使用方法總結(jié):
http://
http://Java.sun.com/javase/6/docs/technotes/tools/share/jconsole.html
在實際測試某一個項目時,內(nèi)存出現(xiàn)泄露現(xiàn)象。起初在性能測試的1個小時中,并不明顯,而在穩(wěn)定性測試的時候才發(fā)現(xiàn),應(yīng)用的HSF調(diào)用在經(jīng)過幾個 小時運行后,就出現(xiàn)性能明顯下降的情況。在服務(wù)日志中報大量HSF超時,但所調(diào)用系統(tǒng)沒有任何超時日志,并且壓力應(yīng)用的load都很低。經(jīng)過查看日志后,認為應(yīng)用可能存在內(nèi)存泄漏。通過jconsole 以及 jmap 工具進行分析發(fā)現(xiàn),確實存在內(nèi)存泄漏問題,其中PS Old Gen最終達到占用 100%的占用。如圖所示:
從上圖可以看到,雖然每次Full GC,JVM內(nèi)存會有部分回收,但回收并不徹底,不可回收的內(nèi)存對象會越來越多,這樣便會出現(xiàn)以上的一個趨勢。在Full GC無法回收的對象越來越多時,最終已使用內(nèi)存達到系統(tǒng)分配的內(nèi)存最大值,系統(tǒng)最后無內(nèi)存可分配,最終down機。
第四部分 分析
經(jīng)過開發(fā)和架構(gòu)師對應(yīng)用的分析,查看此時內(nèi)存隊列,看哪個對象占用數(shù)據(jù)最多,再利用jmap命令,對線程數(shù)據(jù)分析,如下所示:
num #instances #bytes class name
1: 9248056 665860032 com.taobao.matrix.mc.domain.**
2: 9248031 295936992 com.taobao.matrix.**
3: 9248068 147969088 java.util.**
4: 1542111 37010664 java.util.Date
前三個instances不斷增加,指代的是同一個代碼邏輯,異步分發(fā)的問題,堵塞消息,回收多次都無法回收成功。導(dǎo)致內(nèi)存溢出。
此外,對應(yīng)用的性能單獨做了壓測,他的性能只能支撐到一半左右,故發(fā)送消息的TPS,應(yīng)用肯定無法處理過來,導(dǎo)致消息堆積,而JAVA垃圾回收期認為這些都是有用的對象,導(dǎo)致內(nèi)存堆積,直至系統(tǒng)崩潰。
調(diào)優(yōu)方法
由于具體調(diào)優(yōu)方法涉及到應(yīng)用的配置信息,故在此暫不列出,可以參考性能測試小組發(fā)布的《性能測試調(diào)優(yōu)寶典》
第四部分 總結(jié)
內(nèi)存溢出主要是由于代碼編寫時對某些方法、類應(yīng)用不合理,或者沒有預(yù)估到臨時對象會占用很大內(nèi)存量,或者把過多的數(shù)據(jù)放入JVM緩存,或者性能 壓力大導(dǎo)致消息堆積而占用內(nèi)存,以至于在性能測試時,生成龐大數(shù)量的臨時對象,GC時沒有做出有效回收甚至根本就不能回收,造成內(nèi)存空間不足,內(nèi)存溢出。
如果編碼之前,對內(nèi)存使用量進行預(yù)估,對放在內(nèi)存中的數(shù)據(jù)進行評估,保證有用的信息盡快釋放,無用的信息能夠被GC回收,這樣在一定程度上是可以避免內(nèi)存溢出問題的。
第三篇:檢查內(nèi)存泄露
Debug Assertion Failed!
這個錯誤的原因可能是數(shù)組越界或出現(xiàn)了野指針.內(nèi)存釋放(或資源釋放)時出現(xiàn)了錯誤
這是個很一般性的錯誤, 就像Windows報告說執(zhí)行了非法操作一樣.憑此信息無法判 斷具體錯誤位置, 只能靠自己跟蹤了
當出現(xiàn)這個錯誤的時候,我重新檢查了自己new的指針,由于對于這塊很發(fā)怵,所以把所有new的指針都避掉。但還是出現(xiàn)同樣的問題。
后來又上網(wǎng)搜了一下,在《VC++6.0中內(nèi)存泄漏檢測》這篇文章中提到,“可用于被多態(tài)繼承的基類其析構(gòu)函數(shù)應(yīng)當有virtual修飾“的法則(一不小心就忘了寫virtual ^_^),”,哈哈,我也違反了,后來加上virtual后就沒有問題了。
下面把那篇文章貼上來以供自己日后查看。
VC++6.0中內(nèi)存泄漏檢測(轉(zhuǎn))
VC++6.0中內(nèi)存泄漏檢測
這篇文章是對2004-09-02日發(fā)表的《VC++6.0中簡單的內(nèi)存泄漏檢測事例代碼》(已經(jīng)刪除)的更新.對C++代碼而言,內(nèi)存泄漏問題雖然有諸多方法避免,但實際代碼編寫的時候,或出于自信或出于復(fù)雜性的考慮,常常還會用到原始的operator new,這不可避免的會帶來內(nèi)存泄漏的可能,不久前本人因為違反了”可用于被多態(tài)繼承的基類其析構(gòu)函數(shù)應(yīng)當有virtual修飾“的法則(一不小心就忘了寫virtual ^_^),導(dǎo)致了內(nèi)存泄漏,因此我覺得出于安全考慮,在代碼中加入內(nèi)存泄漏檢查機制還是很必要的,也因為這次的內(nèi)存泄漏事件促使我寫出這一篇文章.VC++中本身就有內(nèi)存泄漏檢查的機制,你可以在向?qū)傻闹С諱FC的工程中看到如下代碼:
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
通過它們,你能非常容易的發(fā)現(xiàn)代碼中的內(nèi)存泄漏,但是如果手工將這個功能移植到非MFC工程中去是很繁瑣的一件事,另外它還有一個bug,在多線程并發(fā)調(diào)用這個DEBUG_NEW時會導(dǎo)致系統(tǒng)級錯誤,因此本人在此重寫了這個功能,將以下的debug_new.h和debug_new.cpp添加到工程中,并在需要檢測的cpp中#include ”debug_new.h“和main中一開始處加入REG_DEBUG_NEW宏即可.1.debug_new.h 源代碼
/************************************************************************/ /* comment: 此文件與debug_new.cpp配合使用,用于在調(diào)試期發(fā)現(xiàn)內(nèi)存泄漏 */
/* 僅在VC++編譯器中適用(包括Intel C++,因為它使用了相同的庫)*/
/* 作者: 周星星*/
/* 版權(quán)申明: 無,可任意 使用,修改 和 發(fā)布 */
/************************************************************************/ /* sample
#include
#include ”debug_new.h“ // +
using namespace std;
int main(void)
{
REG_DEBUG_NEW;// +
char* p = new char[2];
cout << ”--End--“ << endl;
return 0;
}
在VC++ IDE中按F5調(diào)試運行將會在Output窗口的Debug頁看到類似如下的提示: Dumping objects->
d:test.cpp(10): {45} normal block at 0x003410C8, 2 bytes long.Data: < > CD CD
Object dump complete.如果不出現(xiàn)如上提示請Rebuild All一次.*/
#ifndef _DEBUG_NEW_H_
#define _DEBUG_NEW_H_
#ifdef _DEBUG
#undef new
extern void _RegDebugNew(void);
extern void* __cdecl operator new(size_t, const char*, int);
extern void __cdecl operator delete(void*, const char*, int);
#define new new(__FILE__, __LINE__)
#define REG_DEBUG_NEW _RegDebugNew();
#else
#define REG_DEBUG_NEW
#endif // _DEBUG
#endif // _DEBUG_NEW_H_
2.debug_new.cpp 源代碼
/************************************************************************/ /* comment: 此文件與debug_new.h配合使用,用于在調(diào)試期發(fā)現(xiàn)內(nèi)存泄漏 */
/* 僅在VC++編譯器中適用(包括Intel C++,因為它使用了相同的庫)*/
/* 作者: 周星星*/
/* 版權(quán)申明: 無,可任意 使用,修改 和 發(fā)布 */
/************************************************************************/ //#include ”debug_new.h“
#ifdef _DEBUG
#include
#include
class _CriSec
{
CRITICAL_SECTION criSection;
public:
_CriSec(){ InitializeCriticalSection(&criSection);}
~_CriSec(){ DeleteCriticalSection(&criSection);}
void Enter(){ EnterCriticalSection(&criSection);}
void Leave(){ LeaveCriticalSection(&criSection);}
} _cs;
void _RegDebugNew(void)
{
_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG | _CRTDBG_LEAK_CHECK_DF);
}
void* __cdecl operator new(size_t nSize, const char* lpszFileName, int nLine)
{
// comment 1: MFC中提供的debug new雖然加了鎖,但我在實際測試的時候發(fā)現(xiàn)多線程并發(fā) // 調(diào)用的時候還是拋出了系統(tǒng)錯誤,所以我在這里加了一個線程互斥量.// comment 2: debug new和debug delete之間需不需要互斥我并不知道,保險起見,我同樣 // 加了線程互斥量.// comment 3: 按照C++標準規(guī)定,在operator new失敗后應(yīng)當調(diào)用set_new_handler設(shè)置的 // 函數(shù),但是MSDN中卻說”頭文件new中的set_new_handler是stub的,而應(yīng)該使 // 用頭文件new.h中的_set_new_handler“,這簡直是滑天下之大稽.// 以下是VC++6.0中的set_new_handler定義:
// new_handler __cdecl set_new_handler(new_handler new_p)
// {
// assert(new_p == 0);// cannot use stub to register a new handler
// _set_new_handler(0);
// return 0;
// }
// 所以我也無計可施,只能舍棄set_new_handler的作用._cs.Enter();
void* p = _malloc_dbg(nSize, _NORMAL_BLOCK, lpszFileName, nLine);
_cs.Leave();
return p;
}
void __cdecl operator delete(void* p, const char* /*lpszFileName*/, int /*nLine*/)
{
_cs.Enter();
_free_dbg(p, _CLIENT_BLOCK);
_cs.Leave();
}
#endif
3.事例代碼
#include
#include ”debug_new.h“
using namespace std;
int main(void)
{
REG_DEBUG_NEW;
char* p = new char[2];
p[0] = 'A';
p[1] = 'B';
cout << ”--End--" << endl;
return 0;
}
4.結(jié)果輸出
在VC++ IDE中按F5調(diào)試運行將會在Output窗口的Debug頁看到類似如下的提示: ……
Dumping objects->
d:test.cpp(10): {45} normal block at 0x003410C8, 2 bytes long.Data:
Object dump complete.……
第四篇:系統(tǒng)應(yīng)用服務(wù)器內(nèi)存溢出解決報告
XXX系統(tǒng)應(yīng)用服務(wù)器內(nèi)存溢出解決報告
xxxx股份有限公司
2010.9
目錄
第一章 問題現(xiàn)象與分析................................................................................2
1.1、問題現(xiàn)象.....................................................................................2 1.2、通常導(dǎo)致這種現(xiàn)象的原因..................................................................2 1.3、xxx社保宕機現(xiàn)象對比分析...............................................................3 第二章
解決方法路線圖..............................................................................4
2.1 jvm的調(diào)整...................................................................................4 2.2 減少jvm內(nèi)存使用..........................................................................5 2.2.1 加快db訪問速度,減少中間件并發(fā)業(yè)務(wù)量.......................................5 2.2.2 限制sql返回結(jié)果集..................................................................6 2.2.3 減少業(yè)務(wù)會話中存放的對象.........................................................6 2.3 補救措施......................................................................................6 第三章、解決結(jié)果與進一步建議......................................................................6
3.1 解決結(jié)果......................................................................................6 3.2 進一步建議...................................................................................7
第一章 問題現(xiàn)象與分析
1.1、問題現(xiàn)象
XXX應(yīng)用服務(wù)器經(jīng)常有內(nèi)存溢出、系統(tǒng)沒有響應(yīng)的現(xiàn)象,尤其在每月的月末最為明顯。目前的應(yīng)用服務(wù)器有三種類型,其中ibm和linux應(yīng)用服務(wù)器報告頻繁出現(xiàn)內(nèi)存溢出或沒有響應(yīng)的現(xiàn)象,hp unix應(yīng)用服務(wù)器相穩(wěn)定。在出現(xiàn)問題期間Weblogic無法響應(yīng)任何客戶端請求,大量請求加載到了這臺沒有響應(yīng)的Server上,最后只有殺掉并重啟這臺應(yīng)用服務(wù)器。
1.2、通常導(dǎo)致這種現(xiàn)象的原因
WLS Server 沒響應(yīng)可能的幾種原因:
xxxx股份有限公司
1、繁重的I/O,呼叫DB時間過長導(dǎo)致中間件內(nèi)存耗盡,server沒有響應(yīng)。
2、程序死循環(huán),loop-backs,這種情況cpu很忙,系統(tǒng)沒有響應(yīng)。
3、連接到外部server,沒響應(yīng),由于網(wǎng)絡(luò)等原因 4、2個以上的執(zhí)行者同步死鎖
5、業(yè)務(wù)量過大,全部線程都被占用,出現(xiàn)隊列等待現(xiàn)象
6、讀寫本地I/O,發(fā)生阻塞
WLS Server 宕機的原因:
? ? ? ? OutOfMemory JNI程序 jvm的bug os的bug 1.3、xxx社保宕機現(xiàn)象對比分析
? 應(yīng)用服務(wù)器沒有響應(yīng)分析
通過初步判斷,對于xxx應(yīng)用服務(wù)器沒有響應(yīng)的情況可以做如下排出法解決: ――程序死循環(huán)
這種情況會導(dǎo)致cpu非常繁忙,而通過目前觀察,每次系統(tǒng)沒響應(yīng)的時候,cpu沒有一直100%忙,另外,對出現(xiàn)問題時的java core分析沒有發(fā)現(xiàn)這類線程,因此可以基本排除這種可能。
――連接到外部server,沒響應(yīng),由于網(wǎng)絡(luò)等原因
目前我們的業(yè)務(wù)基本都是直接通過中間件訪問數(shù)據(jù),沒有通過應(yīng)用服務(wù)器間調(diào)用或多數(shù)據(jù)庫調(diào)用的,基本排除這種可能。――2個以上的執(zhí)行者同步死鎖
這種情況有可能,但比較難找,一般都是業(yè)務(wù)高峰的時候才有可能出現(xiàn),跟應(yīng)用人員了解后得知我們很少使用同步方式實現(xiàn)對資源的共享。另外通過對javacore進行分析,并未發(fā)現(xiàn)同步造成的死鎖現(xiàn)象。
――業(yè)務(wù)量過大,全部線程都被占用,出現(xiàn)隊列等待現(xiàn)象
通過觀察我們的業(yè)務(wù)量在高峰時確實很大,但由于我們配置的線程數(shù)都很高,盡管出現(xiàn)宕機時也沒有達到配置的上線,所以這個方面可以被排除。――繁重的I/O,呼叫DB時間過長導(dǎo)致中間件內(nèi)存耗盡
由于我們經(jīng)常有新業(yè)務(wù)變更,尤其近期還有居民醫(yī)保業(yè)務(wù)上線,因此I/O問題導(dǎo)致
xxxx股份有限公司 的因素也需要重點考察!
――讀寫本地I/O,發(fā)生阻塞,多線程耗盡jvm內(nèi)存
這種現(xiàn)象很可能發(fā)生,應(yīng)重點給予關(guān)注
? 對WLS SERVER 宕機的幾種情況的分析:
――OufOfMemory 目前xxx社保應(yīng)用服務(wù)器出現(xiàn)宕機的時候基本都表現(xiàn)為這種現(xiàn)象,這也是中間件服務(wù)器最常見的現(xiàn)象。原因可能有多種,可能是平臺的,多數(shù)情況下是物理內(nèi)存配置過低,或jvm參數(shù)配置過低造成的。但通過對xxx社保配置參數(shù)進行分析發(fā)現(xiàn)參數(shù)基本合理,除了線程數(shù)和連接池配置稍大點,其它都很正常。由此分析是估計是其它原因造成的。
其它可能的原因可能是平臺原因,比如jvm版本、垃圾回收方式和算法的缺陷等;也可能是應(yīng)用造成的,比如業(yè)務(wù)并發(fā)量過大,內(nèi)存不足造成,也可能是返回大結(jié)果集以及會話存放對象過多等原因。因此重點是找出可行的解決方案,避免出現(xiàn)內(nèi)存溢出,減少對jvm內(nèi)存的使用量。――平臺bug 比如jni、jvm、os的bug等。每個weblogic版本都有對應(yīng)的平臺Jni,用來增加系統(tǒng)性能,但有時表現(xiàn)出不穩(wěn)定的現(xiàn)象。Jvm和os版本對WLS server的穩(wěn)定更是影響很大,通過以前的記錄發(fā)現(xiàn)ibm和linux的應(yīng)用服務(wù)器比hp出現(xiàn)的宕機頻率更多些,因此有必要對ibm和linuxjvm做些分析和調(diào)整。
第二章
解決方法路線圖
通過前面分析把解決問題的路線圖定位在三方面,一個是調(diào)整現(xiàn)有平臺jvm版本和參數(shù),盡量達到平臺的穩(wěn)定性;另外一個是考慮如何減少jvm內(nèi)存的使用上,尤其要解決訪問DB慢以及返回大結(jié)果集這兩方面,以期通過增強訪問速度減少并發(fā)量,減少返回結(jié)果對內(nèi)存的占用,從而使系統(tǒng)不發(fā)生或少發(fā)生OutOfMemory現(xiàn)象。另外,在意外出現(xiàn)宕機的情況下,通過負載均衡器的配置實現(xiàn)新請求直接發(fā)送給其它運行正常的服務(wù)器。
2.1 jvm的調(diào)整
采用方法:
? 調(diào)整ibm應(yīng)用服務(wù)器的 jvm 系統(tǒng)參數(shù) kcluster等,消除內(nèi)存碎片。? 調(diào)整 linux應(yīng)用服務(wù)器的jvm,由bea的jrockit到sun jdk。
xxxx股份有限公司 實際效果:
? Ibm服務(wù)器jvm為1.4.2,由于本版本的垃圾回收算法問題,會出現(xiàn)內(nèi)存碎片,7月份相應(yīng)調(diào)整了jvm參數(shù),不過還是宕機很多次,沒有明顯效果。通過對8月份ibm服務(wù)器一次宕機javacore分析,發(fā)現(xiàn)在高峰階段jvm還是會出現(xiàn)heap lock資源等待現(xiàn)象,經(jīng)查ibm資料,基本上還是證實是內(nèi)存碎片過多,并發(fā)申請內(nèi)存太多導(dǎo)致系統(tǒng)無內(nèi)存可用,最后宕機。不過8月份已經(jīng)好很多了,才發(fā)現(xiàn)一次。這種情況目前最好方法是通過減少并發(fā)量來解決,由于應(yīng)用的原因目前還無法升級jvm。? Linux服務(wù)器的jvm通過從jroick調(diào)整到sun后,在7月份就效果就很好。在8月份系統(tǒng)出現(xiàn)一次沒有響應(yīng)了,當時內(nèi)存還是剩余很多的,現(xiàn)象也是OutOfMemory,但同時報sun javaException in thread “CompilerThread0” java.lang.OutOfMemoryError: requested 32760 bytes forChunkPool::allocate.Out of swap space? 經(jīng)查這種現(xiàn)象跟在linux平臺上jvm虛擬機不穩(wěn)定有關(guān),但這種現(xiàn)象不會經(jīng)常出現(xiàn)。
2.2 減少jvm內(nèi)存使用
想辦法減少jvm內(nèi)存使用量是解決問題的關(guān)鍵,減少應(yīng)用服務(wù)器瞬時的并發(fā)量是一個好的途徑,這就要保證快速的DB訪問,小的結(jié)果集返回,session中少量的保存對象,同時會話保持不宜過長。
2.2.1 加快db訪問速度,減少中間件并發(fā)業(yè)務(wù)量
采用方法1:通過oracle oem等工具跟蹤監(jiān)控大量耗I/O的語句,同時監(jiān)控其它影響db服務(wù)器運行慢的進程。
實際效果:項目組調(diào)整低性能的sql后,該部分業(yè)務(wù)明顯加快,沒有再發(fā)現(xiàn)相關(guān)業(yè)務(wù)的大量全表掃描等情況。
采用方法2:對影響應(yīng)收預(yù)覽速度的ac40瘦身,重建并進行了分區(qū)。實際效果:根據(jù)現(xiàn)場反映速度有些提升。但由于對另外一個影響速度的關(guān)鍵表ab30無法瘦身(醫(yī)保業(yè)務(wù)用),目前應(yīng)收預(yù)覽速度要有質(zhì)的飛躍還很難。
xxxx股份有限公司
2.2.2 限制sql返回結(jié)果集
采用方法:從底層編寫監(jiān)控sql返回的大結(jié)果集程序,可定制記錄數(shù)等參數(shù)
實際效果:目前已經(jīng)抓到很多大sql,返回的結(jié)果集從幾千達到10幾萬以上,基本消除了大結(jié)果集造成的原因,長期部署可對新程序新業(yè)務(wù)的大結(jié)果集檢驗有非常大的好處。
2.2.3 減少業(yè)務(wù)會話中存放的對象
采用方法:減少會話中的存放對象數(shù),把沒有必要或不需要使用的對象從會話中清除。
實際效果:這是一個備用手段,由于是改動了程序,為了生產(chǎn)安全考慮,暫時沒有部署,在其它手段沒有效果的情況下經(jīng)過測試后再把它加載上去。
2.3 對本地讀寫的定位
通過對大量ibm java core分析,發(fā)現(xiàn)有讀寫I/O導(dǎo)致的堵塞。
2.4 補救措施
方法:在應(yīng)用服務(wù)器上部署一個test.html靜態(tài)頁面,同時在負載均衡器上配置對這個靜態(tài)頁面的定時訪問。
結(jié)果:通過8月份業(yè)務(wù)的實際運行考驗確實起到了作用,7月份當一臺服務(wù)器沒有響應(yīng)的時候馬上就有業(yè)務(wù)人員反映,8月份卻沒有,同時我們也發(fā)現(xiàn)了的確新的請求就不再發(fā)給問題服務(wù)器,重新啟動后新請求一點一點的加載上來,改善是很有效果的。
第三章、解決結(jié)果與進一步建議
3.1 解決結(jié)果
通過兩個月周期的現(xiàn)場分析、調(diào)整,目前應(yīng)用服務(wù)器系統(tǒng)穩(wěn)定性已經(jīng)明顯提高了。盡管
xxxx股份有限公司 月底個別高峰的時候還會出現(xiàn)系統(tǒng)沒有響應(yīng)情況,但通過其它手段彌補已經(jīng)不會影響業(yè)務(wù)的運行。
分析導(dǎo)致系統(tǒng)宕機因素是多方面的,包括java平臺的原因,程序大結(jié)果集的原因,表數(shù)據(jù)量大/sql程序不夠優(yōu)化的原因,陣列I/O性能的原因、并發(fā)大業(yè)務(wù)的等原因。這些原因往往交織在一起,呈現(xiàn)出各種系統(tǒng)宕機狀況。但最終只要我們提高sql的運行速度,降低jvm的內(nèi)存使用量,把握好大的結(jié)果集和大的業(yè)務(wù)對象使用,盡管jvm本身有不穩(wěn)定的情況,也不會或很少出現(xiàn)jvm宕機現(xiàn)象的。
3.2 進一步建議
? 優(yōu)化或升級現(xiàn)有陣列
目前整體系統(tǒng)的瓶頸在I/O上,希望考慮陣列升級計劃。? 對目前業(yè)務(wù)數(shù)據(jù)和程序做一個周期瘦身和優(yōu)化方案
從系統(tǒng)整體性能分析看,不良的I/O狀況,越來越多的上億記錄的表導(dǎo)致大量對數(shù)據(jù)庫操作業(yè)務(wù)緩慢,使中間件服務(wù)器并發(fā)量瞬時增加,中間件服務(wù)器的負載量加重,也成為中間件的宕機的一個主要原因。
? 優(yōu)化本地I/O讀寫,將日志調(diào)試信息去掉。
? 對新業(yè)務(wù)繼續(xù)監(jiān)控大結(jié)果集(目前部署在11、12上)。
? 對新業(yè)務(wù)繼續(xù)要做及時監(jiān)控,抓大sql(耗I/O量大,運行次數(shù)多,阻塞其它業(yè)務(wù))。
xxxx股份有限公司
第五篇:C與C 經(jīng)典面試題(內(nèi)存泄露)匯總
C、C++語言面試題2007-07-15 18:57 1.已知strcpy 函數(shù)的原型是:
char *strcpy(char *strDest, const char *strSrc);其中strDest 是目的字符串,strSrc 是源字符串。不調(diào)用C++/C 的字符串庫函數(shù),請編寫函數(shù) strcpy 答案:
char *strcpy(char *strDest, const char *strSrc){ if(strDest == NULL || strSrc == NULL)return NULL;if(strDest == strSrc)return strDest;char *tempptr = strDest;while((*strDest++ = *strSrc++)!= ‘ 主站蜘蛛池模板: 亚洲国产成人av在线电影播放| 少妇人妻综合久久中文字幕| 国产精品美女www爽爽爽视频| 熟妇人妻中文av无码| 免费人妻无码不卡中文18禁| 亚洲精品一卡2卡3卡4卡乱码| 国产高清一区二区三区视频| 双乳被老汉揉搓a毛片免费观看| 狠狠躁天天躁夜夜躁婷婷| 精品视频一区二区| 特级做a爰片毛片免费69| 人妻天天爽夜夜爽一区二区| 精品国产av 无码一区二区三区| 日韩精品区一区二区三vr| 久久久久久人妻无码| 精品国精品无码自拍自在线| 色欲人妻aaaaaa无码| 中文字幕久久精品一二三区| 国产免费一区二区三区在线观看| 亚洲国产精品成人无码区| 蜜桃mv在线播放免费观看视频| 四虎国产精品永久地址99| 黑人巨大av无码专区| 久久欧美一区二区三区性生奴| 亚洲欧洲美色一区二区三区| 国产av毛片亚洲含羞草社| 精品无码一区在线观看| 一本精品99久久精品77| 成人精品视频一区二区不卡| 两个人看的www免费视频中文| 国产激情久久久久久熟女老人| 精品久久久久久久国产潘金莲| 国精产品一品二品国精在线观看| 国产对白叫床清晰在线播放| 久久久www成人免费无遮挡大片| 精品精品自在现拍国产2021| 亚洲va无码手机在线电影| 久久久久99精品成人片试看| 9色国产深夜内射| 337p亚洲日本中国大胆69| 日韩无码在钱中文字幕在钱视频|