導航:首頁 > 配伺服器 > 怎麼排查伺服器是否存在內存泄漏

怎麼排查伺服器是否存在內存泄漏

發布時間:2024-07-28 21:04:53

『壹』 如何監測windows伺服器的性能

Windows伺服器中自帶的性能監控工具叫做Performance Monitor;

在開始-運行中輸入『perfmon』,然後回車即可運行。

Monitor本身也是一個進程,運行起來也要佔用一定的系統資源。所以你看到的資源的使用量應該比實際的要稍微高一點。這個工具在幫助管理員判斷系統性能瓶頸時非常有用;

舉個列子來說,今天有個用戶抱怨說他們項目組的伺服器(這是一台虛擬機)運行消告哪起來非常慢,但也不知道具體問題出在什麼地方。任務管理器里顯示CPU和內存的使用量都不算高,但伺服器的相應就是非常慢;

Monitor,讓拿碼其運行一段時間後(因為參考平均值會比較准確),發現average disk queue的值比較高,這就說明物理伺服器的硬碟負荷太重,I/O操作的速度跟不上系統的要求。關掉虛擬機,將其轉移到另一台硬碟負載比較小的主機上,再打開虛擬機。

『貳』 濡備綍媯嫻嬪唴瀛樻硠婕

鍐呭瓨娉勬紡鎸囩敱浜庣枏蹇芥垨閿欒閫犳垚紼嬪簭鏈鑳介噴鏀懼凡緇忎笉鍐嶄嬌鐢ㄧ殑鍐呭瓨鐨勬儏鍐點傚唴瀛樻硠婕忓苟闈炴寚鍐呭瓨鍦ㄧ墿鐞嗕笂鐨勬秷澶憋紝鑰屾槸搴旂敤紼嬪簭鍒嗛厤鏌愭靛唴瀛樺悗錛岀敱浜庤捐¢敊璇錛屽け鍘諱簡瀵硅ユ靛唴瀛樼殑鎺у埗錛屽洜鑰岄犳垚浜嗗唴瀛樼殑嫻璐廣
鍙浠ヤ嬌鐢ㄧ浉搴旂殑杞浠舵祴璇曞伐鍏峰硅蔣浠惰繘琛屾嫻嬨
1. ccmalloc鈥斺擫inux鍜孲olaris涓嬪笴鍜孋++紼嬪簭鐨勭畝鍗曠殑浣跨敤鍐呭瓨娉勬紡鍜宮alloc璋冭瘯搴撱
2. Dmalloc鈥斺擠ebug Malloc Library.
3. Electric
Fence鈥斺擫inux鍒嗗彂鐗堜腑鐢盉ruce Perens緙栧啓鐨刴alloc錛堬級璋冭瘯搴撱
4. Leaky鈥斺擫inux涓嬫嫻嬪唴瀛樻硠婕忕殑紼嬪簭銆
5. LeakTracer鈥斺擫inux銆丼olaris鍜孒P-UX涓嬭窡韙鍜屽垎鏋怌++紼嬪簭涓鐨勫唴瀛樻硠婕忋
6. MEMWATCH鈥斺旂敱Johan
Lindh緙栧啓錛屾槸涓涓寮鏀炬簮浠g爜C璇璦鍐呭瓨閿欒媯嫻嬪伐鍏鳳紝涓昏佹槸閫氳繃gcc鐨刾recessor鏉ヨ繘琛屻
7. Valgrind鈥斺擠ebugging and profiling Linux programs, aiming at
programs written in C and C++.
8. KCachegrind鈥斺擜 visualization tool for the profiling data
generated by Cachegrind and Calltree.
9. Leak
Monitor鈥斺斾竴涓狥irefox鎵╁睍錛岃兘鎵懼嚭璺烣irefox鐩稿叧鐨勬硠婕忕被鍨嬨
10. IE Leak Detector
錛圖rip/IE Sieve錛夆斺擠rip鍜孖E Sieve leak
detectors甯鍔╃綉欏靛紑鍙戝憳鎻愬崌鍔ㄦ佺綉欏墊ц兘閫氳繃鎶ュ憡鍙閬垮厤鐨勫洜涓篒E灞闄愮殑鍐呭瓨娉勬紡銆
11. Windows Leaks
Detector鈥斺旀帰嫻嬩換浣昗in32搴旂敤紼嬪簭涓鐨勪換浣曡祫婧愭硠婕忥紙鍐呭瓨錛屽彞鏌勭瓑錛夛紝鍩轟簬Win API璋冪敤閽╁瓙銆
12. SAP Memory
Analyzer鈥斺旀槸涓嬈懼紑婧愮殑java鍐呭瓨鍒嗘瀽杞浠訛紝鍙鐢ㄤ簬杈呭姪鏌ユ壘JAVA紼嬪簭鐨勫唴瀛樻硠婕忥紝鑳藉規槗鎵懼埌澶у潡鍐呭瓨騫墮獙璇佽皝鍦ㄤ竴鐩村崰鐢ㄥ畠錛屽畠鏄鍩轟簬Eclipse
RCP錛圧ich Client Platform錛夛紝鍙浠ヤ笅杞絉CP鐨勭嫭絝嬬増鏈鎴栬匛clipse鐨勬彃浠躲
13. DTrace鈥斺斿嵆鍔ㄦ佽窡韙狣ynamic
Tracing錛屾槸涓嬈懼紑婧愯蔣浠訛紝鑳藉湪Unix綾諱技騫沖彴榪愯岋紝鐢ㄦ埛鑳藉熷姩鎬佹嫻嬫搷浣滅郴緇熷唴鏍稿拰鐢ㄦ埛榪涚▼錛屼互鏇寸簿紜鍦版帉鎻$郴緇熺殑璧勬簮浣跨敤鐘跺喌錛屾彁楂樼郴緇熸ц兘錛屽噺灝戞敮鎸佹垚鏈錛屽苟榪涜屾湁鏁堢殑璋冭妭銆
14. IBM Rational PurifyPlus鈥斺斿府鍔╁紑鍙戜漢鍛樻煡鏄嶤/C++銆佹墭綆°侼ET銆丣ava鍜孷B6浠g爜涓鐨勬ц兘鍜屽彲闈犳ч敊璇銆侾urifyPlus
灝嗗唴瀛橀敊璇鍜屾硠婕忔嫻嬨佸簲鐢ㄧ▼搴忔ц兘鎻忚堪銆佷唬鐮佽嗙洊鍒嗘瀽絳夊姛鑳界粍鍚堝湪涓涓鍗曚竴銆佸畬鏁寸殑宸ュ叿鍖呬腑銆
15. Parasoft Insure++鈥斺旈拡瀵笴/C++搴旂敤鐨勮繍琛屾椂閿欒鑷鍔ㄦ嫻嬪伐鍏鳳紝瀹冭兘澶熻嚜鍔ㄧ洃嫻婥/C++紼嬪簭錛屽彂鐜板叾涓瀛樺湪鐫鐨勫唴瀛樼牬鍧忋佸唴瀛樻硠婕忋佹寚閽堥敊璇鍜孖/O絳夐敊璇銆傚苟閫氳繃浣跨敤涓緋誨垪鐙鐗圭殑鎶鏈錛圫CI鎶鏈鍜屽彉寮傛祴璇曠瓑錛夛紝褰誨簳鐨勬鏌ュ拰嫻嬭瘯鎴戜滑鐨勪唬鐮侊紝綺劇『瀹氫綅閿欒鐨勫噯紜浣嶇疆騫剁粰鍑鴻︾粏鐨勮瘖鏂淇℃伅銆傝兘浣滀負Microsoft
Visual C++鐨勪竴涓鎻掍歡榪愯屻
16. Compuware DevPartner for Visual C++ BoundsChecker
Suite鈥斺斾負C++寮鍙戣呰捐$殑榪愯岄敊璇媯嫻嬪拰璋冭瘯宸ュ叿杞浠躲備綔涓篗icrosoft Visual Studio鍜孋++ 6.0鐨勪竴涓鎻掍歡榪愯屻
17. Electric Software GlowCode鈥斺斿寘鎷鍐呭瓨娉勬紡媯鏌ワ紝code
profiler錛屽嚱鏁拌皟鐢ㄨ窡韙絳夊姛鑳姐傜粰C++鍜屻侼et寮鍙戣呮彁渚涘畬鏁寸殑閿欒璇婃柇錛屽拰榪愯屾椂鎬ц兘鍒嗘瀽宸ュ叿鍖呫
18. Compuware DevPartner Java
Edition鈥斺斿寘鍚獼ava鍐呭瓨媯嫻嬶紝浠g爜瑕嗙洊鐜囨祴璇曪紝浠g爜鎬ц兘嫻嬭瘯錛岀嚎紼嬫婚攣錛屽垎甯冨紡搴旂敤絳夊嚑澶у姛鑳芥ā鍧椼
19. Quest JProbe鈥斺斿垎鏋怞ava鐨勫唴瀛樻硠婕忋
20. ej-technologies JProfiler鈥斺斾竴涓鍏ㄥ姛鑳界殑Java鍓栨瀽宸ュ叿錛屼笓鐢ㄤ簬鍒嗘瀽J2SE鍜孞2EE搴旂敤紼嬪簭銆傚畠鎶奀PU銆佹墽琛岀華鍜屽唴瀛樼殑鍓栨瀽緇勫悎鍦ㄤ竴涓寮哄ぇ鐨勫簲鐢ㄤ腑銆侸Profiler鍙鎻愪緵璁稿欼DE鏁村悎鍜屽簲鐢ㄦ湇鍔″櫒鏁村悎鐢ㄩ斻侸Profiler鐩磋夊紡鐨凣UI璁╀綘鍙浠ユ壘鍒版晥鑳界摱棰堛佹姄鍑哄唴瀛樻硠婕忋佸苟瑙e喅鎵ц岀華鐨勯棶棰樸4.3.2娉ㄥ唽鐮侊細A-G666#76114F-1olm9mv1i5uuly#0126
21. BEA JRockit鈥斺旂敤鏉ヨ瘖鏂璊ava鍐呭瓨娉勬紡騫舵寚鍑烘牴鏈鍘熷洜錛屼笓闂ㄩ拡瀵笽ntel騫沖彴騫跺緱鍒頒紭鍖栵紝鑳藉湪Intel紜浠朵笂鑾峰緱鏈楂樼殑鎬ц兘銆
22. SciTech Software AB .NET Memory
Profiler鈥斺旀壘鍒板唴瀛樻硠婕忓苟浼樺寲鍐呭瓨浣跨敤閽堝笴#錛孷B.Net錛屾垨鍏跺畠銆侼et紼嬪簭銆
23. YourKit .NET & Java Profiler鈥斺斾笟鐣岄嗗厛鐨凧ava鍜屻侼ET紼嬪簭鎬ц兘鍒嗘瀽宸ュ叿銆
24. AutomatedQA AQTime鈥斺擜utomatedQA鐨勮幏濂栦駭鍝乸erformance profiling鍜宮emory
debugging宸ュ叿闆嗙殑涓嬩竴浠f浛鎹浜у搧錛屾敮鎸丮icrosoft, Borland, Intel, Compaq 鍜
GNU緙栬瘧鍣ㄣ傚彲浠ヤ負銆侼ET鍜學indows紼嬪簭鐢熸垚鍏ㄩ潰緇嗚嚧鐨勬姤鍛婏紝浠庤屽府鍔╂偍杞繪澗闅旂誨苟鎺掗櫎浠g爜涓鍚鏈夌殑鎬ц兘闂棰樺拰鍐呭瓨/璧勬簮娉勯湶闂棰樸傛敮鎸併侼et
1.0,1.1,2.0,3.0鍜學indows 32/64浣嶅簲鐢ㄧ▼搴忋
25. JavaScript Memory Leak Detector鈥斺斿井杞鍏ㄧ悆浜у搧寮鍙戞ф床鍥㈤槦錛圙lobal Proct
Development- Europe team, GPDE錛
鍙戝竷鐨勪竴嬈捐皟璇曞伐鍏鳳紝鐢ㄦ潵鎺㈡祴JavaScript浠g爜涓鐨勫唴瀛樻硠婕忥紝榪愯屼負IE緋誨垪鐨勪竴涓鎻掍歡銆

『叄』 如何定位java內存泄露

1、為什麼會發生內存泄漏

Java如何檢測內在泄漏呢?我們需要一些工具進行檢測,並發現內存泄漏問題,不然很容易發生down機問題。

編寫java程序最為方便的地方就是我們不需要管理內存的分配和釋放,一切由jvm來進行處理,當java對象不再被應用時,等到堆內存不夠用時,jvm會進行垃圾回收,清除這些對象佔用的堆內存空間,如果對象一直被應用,jvm無法對其進行回收,創建新的對象時,無法從Heap中獲取足夠的內存分配給對象,這時候就會導致內存溢出。而出現內存泄露的地方,一般是不斷的往容器中存放對象,而容器沒有相應的大小限制或清除機制。容易導致內存溢出。
當伺服器應用佔用了過多內存的時候,如何快速定位問題呢?現在,Eclipse MAT的出現使這個問題變得非常簡單。EclipseMAT是著名的SAP公司貢獻的一個工具,可以在Eclipse網站下載到它,完全免費的。
要定位問題,首先你需要獲取伺服器jvm某刻內存快照。jdk自帶的jmap可以獲取內存某一時刻的快照,導出為dmp文件後,就可以用Eclipse MAT來分析了,找出是那個對象使用內存過多。

2、內存泄漏的現象:

常常地,程序內存泄漏的最初跡象發生在出錯之後,在你的程序中得到一個OutOfMemoryError。這種典型的情況發生在產品環境中,而在那裡,你希望內存泄漏盡可能的少,調試的可能性也達到最小。也許你的測試環境和產品的系統環境不盡相同,導致泄露的只會在產品中暴露。這種情況下,你需要一個低負荷的工具來監聽和尋找內存泄漏。同時,你還需要把這個工具同你的系統聯系起來,而不需要重新啟動他或者機械化你的代碼。也許更重要的是,當你做分析的時候,你需要能夠同工具分離而使得系統不會受到干擾。
一個OutOfMemoryError常常是內存泄漏的一個標志,有可能應用程序的確用了太多的內存;這個時候,你既不能增加JVM的堆的數量,也不能改變你的程序而使得他減少內存使用。但是,在大多數情況下,一個OutOfMemoryError是內存泄漏的標志。一個解決辦法就是繼續監聽GC的活動,看看隨時間的流逝,內存使用量是否會增加,如果有,程序中一定存在內存泄漏。

3、發現內存泄漏

1. jstat -gc pid

可以顯示gc的信息,查看gc的次數,及時間。

其中最後五項,分別是young gc的次數,young gc的時間,full gc的次數,full gc的時間,gc的總時間。

2.jstat -gccapacity pid

可以顯示,VM內存中三代(young,old,perm)對象的使用和佔用大小,

如:PGCMN顯示的是最小perm的內存使用量,PGCMX顯示的是perm的內存最大使用量,

PGC是當前新生成的perm內存佔用量,PC是但前perm內存佔用量。

其他的可以根據這個類推,OC是old內純的佔用量。

3.jstat -gcutil pid

統計gc信息統計。

4.jstat -gcnew pid

年輕代對象的信息。

5.jstat -gcnewcapacity pid

年輕代對象的信息及其佔用量。

6.jstat -gcold pid

old代對象的信息。

7.stat -gcoldcapacity pid

old代對象的信息及其佔用量。

8.jstat -gcpermcapacity pid

perm對象的信息及其佔用量。

9.jstat -class pid

顯示載入class的數量,及所佔空間等信息。
10.jstat -compiler pid

顯示VM實時編譯的數量等信息。

11.stat -printcompilation pid

當前VM執行的信息。

一些術語的中文解釋:

S0C:年輕代中第一個survivor(倖存區)的容量(位元組)
S1C:年輕代中第二個survivor(倖存區)的容量(位元組)
S0U:年輕代中第一個survivor(倖存區)目前已使用空間(位元組)
S1U:年輕代中第二個survivor(倖存區)目前已使用空間(位元組)
EC:年輕代中Eden(伊甸園)的容量(位元組)
EU:年輕代中Eden(伊甸園)目前已使用空間(位元組)
OC:Old代的容量(位元組)
OU:Old代目前已使用空間(位元組)
PC:Perm(持久代)的容量(位元組)
PU:Perm(持久代)目前已使用空間(位元組)
YGC:從應用程序啟動到采樣時年輕代中gc次數
YGCT:從應用程序啟動到采樣時年輕代中gc所用時間(s)
FGC:從應用程序啟動到采樣時old代(全gc)gc次數
FGCT:從應用程序啟動到采樣時old代(全gc)gc所用時間(s)
GCT:從應用程序啟動到采樣時gc用的總時間(s)

NGCMN:年輕代(young)中初始化(最小)的大小(位元組)

NGCMX:年輕代(young)的最大容量(位元組)

NGC:年輕代(young)中當前的容量(位元組)

OGCMN:old代中初始化(最小)的大小(位元組)

OGCMX:old代的最大容量(位元組)

OGC:old代當前新生成的容量(位元組)

PGCMN:perm代中初始化(最小)的大小(位元組)

PGCMX:perm代的最大容量(位元組)

PGC:perm代當前新生成的容量(位元組)

S0:年輕代中第一個survivor(倖存區)已使用的占當前容量百分比

S1:年輕代中第二個survivor(倖存區)已使用的占當前容量百分比

E:年輕代中Eden(伊甸園)已使用的占當前容量百分比

O:old代已使用的占當前容量百分比

P:perm代已使用的占當前容量百分比

S0CMX:年輕代中第一個survivor(倖存區)的最大容量(位元組)

S1CMX:年輕代中第二個survivor(倖存區)的最大容量(位元組)

ECMX:年輕代中Eden(伊甸園)的最大容量(位元組)

DSS:當前需要survivor(倖存區)的容量(位元組)(Eden區已滿)

TT:持有次數限制

MTT:最大持有次數限制

如果定位內存泄漏問題我一般使用如下命令

Jstat -gcutil15469 2500 70

其中深藍色的部分就為內存泄漏的部分,java的堆內存一共只有481.5M而內存泄漏的部分獨自佔有了336.2M所以本次的內存泄漏很明顯,那麼我就來看看那個方法導致的內存泄漏:

從上圖我們可以發現紅線圈著的方法佔用了堆內存的67.75%,如果能把這個測試結果交給開發,開發是不是應該很好定位呢。所以作為一名高級測試工程師,我們需要學習的東西太多。

雖然不確定一定是內存泄漏,但是可以准確的告訴開發問題出現的原因,有一定的說服力。

『肆』 記一次服務Full GC背後的內存泄漏問題,真是匪夷所思

最近所負責的服務略頻繁地收到4xx告警

1、查業務日誌,沒發現相關錯誤的日誌
2、查nginx access log,發現返回的狀態碼都是499,從request_uri查了一遍發現不是集中在某一個請求上,說明應該不是某個介面的問題了,有可能進程層面問題了。

通過對upstream_addr 分類,可以看到問題基本都是集中在 某一台這台機器上

3、網上資料了解到,499 是 nginx 擴展的 4xx 錯誤,代表客戶端請求還未返回時,客戶端主動斷開連接。原因有幾種,不過大部分原因都說到有可能伺服器upstream處理過慢,導致用戶提前關閉連接。那就先往這個方向排查,登錄機器查看實際的access.log

發現upstream response都是10s以上。這就證明了上游伺服器處理10秒還沒有響應,因此nginx提前關閉鏈接,返回499

4、為什麼進程響應如此慢,10秒太不正常了。考慮到那段時間就只有一台機器有問題,而且是進程層面的問題,首先想到的是GC,於是再次登錄到機器上查看gc log。發現有Full GC,時間點和告警的時間也吻合。 驚呆的是,這次FullGC耗時長達19.07秒,由於我們的服務使用的是jdk8默認的ParallelGC,FullGC期間,整個應用Stop The World的。這是非常恐怖的一件事

由此看來,4xx告警的初步原因已經定位到,就是FullGC導致的。

那麼究竟為什麼會發生FullGC呢?需要深入分析一下。
藉助服務治理平台的JVM監控觀察了幾天。期間不同機器不同時間也發生了幾次FullGC。從監控發現,基本每台機器隔兩天就會發生一次FullGC,每次FullGC後年老代回收的垃圾不算多,使用比例還是挺高的。

為什麼年老代空間佔用這么多?

繼續分析上面那條full gc log,
1、發生full gc時,年老代內存已經佔用了99.98%了(1048397/1048576)。看起來因為年老代滿了而觸發的FullGC了。
2、full gc回收了年老代大約302M的垃圾,回收後年老代佔用70.4%(738282/1048576)。這佔用率還是比較高的。

1、首先jmap簡單列印一下所有對象的信息。發現有ClassPathList和ClassClassPath兩個類的對象數量高達1000多萬,並且這兩個數量是一樣的。彷彿嗅到了內存泄漏的味道。

2、只依靠對象統計信息,不足以定位問題,需要使用完整HeapDump,通過MAT進一步分析

jmap把完整堆heapDump下來

隔一段時間後,繼續jmap,這次只取存活對象的mp(實際效果是先執行一次FULL GC)

可以看到,經過Full GC後,ClassPathList對象沒有被回收,數量反而繼續增加。到這里,基本可以確定,ClassPathList是存在泄漏了。

那麼,ClassPathList究竟被誰引用著,導致回收不掉呢?
通過MAT的OQL過濾出老生代的ClassPathList對象,從對象的關聯關繫上繼續深入分析。

首先需要知道老生代的地址區間,可以使用vjtools

通過vjmap的address命令,快速列印各代地址。

可以得知,oldGen的下界是0x80000000,上界是0xc0000000(注意OQL中使用時要把數值前的那串0去掉)。

執行OQL只查詢年老代中的ClassPathList對象:執行OQL只查詢年老代中的ClassPathList對象:

抽取其中一個對象分析,可以發現這個ClassPathList對象被一連串不同ClassPathList對象的next屬性引用著。看起來是個鏈表的結構

再看看GCRoot,發現是被AppClassLoader也就是我們的應用類載入器引用著。除非這個載入器卸載了,否則ClassPathList對象是不會被GC掉了。

分析到這里,似乎離真相越來越近了。到底這個ClassPathList在項目中哪裡使用到了?
通過前面的分析知道了ClassPathList的整體引用關系鏈:
AppClassLoader -> ClassPool類的defaultPool欄位 -> ClassPoolTail類的source欄位 -> ClassPathList類的pathList

可以看到,ClassPathList有兩個屬性,一個是next,結合之前MAT的分析,ClassPathList的確就是一個鏈表的結構。隨著時間的增長,ClassPathList不斷新增,鏈表也隨之變得越來越大,最後內存佔用逐漸上升。
另一個path欄位屬於ClassPath類型,ClassPath是個介面,查看它的實現類,發現一個似曾相識的名稱ClassClassPath,之前分析對象統計信息時,還有一個類的對象數量是和ClassPathList一樣的,正是這個ClassClassPath。每新增一個ClassPathList,都會伴隨著新增對應的ClassPath對象,這也解釋了為什麼兩者數量是一致的了。

通過注釋知道,這個ClassClassPath的作用大概就是,利用一個叫ClassPool的對象,可以調用其insertClassPath方法來新增一個ClassClassPath對象,insertClassPath方法內部通過頭插法將ClassClassPath添加到ClassPathList鏈表,從而形成一個search-path,然後通過這個search-path能夠獲取到某一個Class類的信息。

於是嘗試著搜了一下,看看項目中有沒有調用到insertClassPath方法的地方。意外發現一個類,

這不就是我們項目用來列印方法入參、執行耗時、上報metrics的@AutoLog的實現類嗎。

可以看到getParams方法中調用了insertClassPath,註解@AutoLog的printParams默認為true,也就是每次調用都需要列印方法入參,每次列印前都要調用getParams先獲取參數名稱。因此每次都會insertClassPath,從而導致ClassPathList鏈表越來越大。

至此,內存泄漏的元兇已經找到。解決方法也就簡單了。
因為目標只是想得到方法的參數名稱,通過JoinPoint其實能直接獲取到,因此可以改成JoinPoint獲取的方式。

為了進行對比,分別在修改前後各進行一次壓測。壓測JVM參數大致與線上一致,為了盡快看到效果,只是調小了heap的大小。-Xms200m -Xmx200m

ClassPathList數量不斷增長

年老代每次能回收的垃圾越來越少,每次回收過後的剩餘空間也越來越小。最終整個年老代被撐滿

雖然還沒觸發OOM,但是CPU負載飆高,從基本都在處於頻繁的FULLGC狀態

ClassPathList已經被消滅掉了

FullGC也趨於規律化了。每次回收的垃圾大致都相同

第一種方式是在啟動參數增加 -XX:+PrintHeapAtGC,每次GC都列印地址

第二種方式是使用vjmap的命令,在-old, -sur, -address 中,都會列印出該區間的地址

第三種方式,使用vjmap的address命令,快速列印各代地址,不會造成過長時間停頓。

附: 我們服務的JVM參數

『伍』 內存溢出和內存泄漏的區別,產生原因以及解決方案

內存溢出 out of memory,是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是內存溢出。
內存泄露 memory leak,是指程序在申請內存後,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積後果很嚴重,無論多少內存,遲早會被佔光。
memory leak會最終會導致out of memory!
內存溢出就是你要求分配的內存超出了系統能給你的,系統不能滿足需求,於是產生溢出。

內存泄漏是指你向系統申請分配內存進行使用(new),可是使用完了以後卻不歸還(delete),結果你申請到的那塊內存你自己也不能再訪問(也許你把它的地址給弄丟了),而系統也不能再次將它分配給需要的程序。一個盤子用盡各種方法只能裝4個果子,你裝了5個,結果掉倒地上不能吃了。這就是溢出!比方說棧,棧滿時再做進棧必定產生空間溢出,叫上溢,棧空時再做退棧也產生空間溢出,稱為下溢。就是分配的內存不足以放下數據項序列,稱為內存溢出.

以發生的方式來分類,內存泄漏可以分為4類:

1. 常發性內存泄漏。發生內存泄漏的代碼會被多次執行到,每次被執行的時候都會導致一塊內存泄漏。
2. 偶發性內存泄漏。發生內存泄漏的代碼只有在某些特定環境或操作過程下才會發生。常發性和偶發性是相對的。對於特定的環境,偶發性的也許就變成了常發性的。所以測試環境和測試方法對檢測內存泄漏至關重要。
3. 一次性內存泄漏。發生內存泄漏的代碼只會被執行一次,或者由於演算法上的缺陷,導致總會有一塊僅且一塊內存發生泄漏。比如,在類的構造函數中分配內存,在析構函數中卻沒有釋放該內存,所以內存泄漏只會發生一次。
4. 隱式內存泄漏。程序在運行過程中不停的分配內存,但是直到結束的時候才釋放內存。嚴格的說這里並沒有發生內存泄漏,因為最終程序釋放了所有申請的內存。但是對於一個伺服器程序,需要運行幾天,幾周甚至幾個月,不及時釋放內存也可能導致最終耗盡系統的所有內存。所以,我們稱這類內存泄漏為隱式內存泄漏。

從用戶使用程序的角度來看,內存泄漏本身不會產生什麼危害,作為一般的用戶,根本感覺不到內存泄漏的存在。真正有危害的是內存泄漏的堆積,這會最終消耗盡系統所有的內存。從這個角度來說,一次性內存泄漏並沒有什麼危害,因為它不會堆積,而隱式內存泄漏危害性則非常大,因為較之於常發性和偶發性內存泄漏它更難被檢測到

內存溢出的原因以及解決方法
引起內存溢出的原因有很多種,小編列舉一下常見的有以下幾種:
1.內存中載入的數據量過於龐大,如一次從資料庫取出過多數據;
2.集合類中有對對象的引用,使用完後未清空,使得JVM不能回收;
3.代碼中存在死循環或循環產生過多重復的對象實體;
4.使用的第三方軟體中的BUG;
5.啟動參數內存值設定的過小
內存溢出的解決方案:
第一步,修改JVM啟動參數,直接增加內存。(-Xms,-Xmx參數一定不要忘記加。)
第二步,檢查錯誤日誌,查看「OutOfMemory」錯誤前是否有其它異常或錯誤。
第三步,對代碼進行走查和分析,找出可能發生內存溢出的位置。
重點排查以下幾點:
1.檢查對資料庫查詢中,是否有一次獲得全部數據的查詢。一般來說,如果一次取十萬條記錄到內存,就可能引起內存溢出。這個問題比較隱蔽,在上線前,資料庫中數據較少,不容易出問題,上線後,資料庫中數據多了,一次查詢就有可能引起內存溢出。因此對於資料庫查詢盡量採用分頁的方式查詢。
2.檢查代碼中是否有死循環或遞歸調用。
3.檢查是否有大循環重復產生新對象實體。
4.檢查對資料庫查詢中,是否有一次獲得全部數據的查詢。一般來說,如果一次取十萬條記錄到內存,就可能引起內存溢出。這個問題比較隱蔽,在上線前,資料庫中數據較少,不容易出問題,上線後,資料庫中數據多了,一次查詢就有可能引起內存溢出。因此對於資料庫查詢盡量採用分頁的方式查詢。
5.檢查List、MAP等集合對象是否有使用完後,未清除的問題。List、MAP等集合對象會始終存有對對象的引用,使得這些對象不能被GC回收。
第四步,使用內存查看工具動態查看內存使用情況

閱讀全文

與怎麼排查伺服器是否存在內存泄漏相關的資料

熱點內容
python啟動時提示沒有入口 瀏覽:678
linux中oracle監聽 瀏覽:618
程序員高價值朋友圈 瀏覽:486
雲伺服器做淘寶店 瀏覽:802
程序員判3年緩3年 瀏覽:909
伺服器雲監控系統 瀏覽:651
ios暴力解壓軟體 瀏覽:430
可以搜簡便演算法的軟體 瀏覽:200
各種的解壓小玩具 瀏覽:933
百度雲伺服器bcc域名綁定 瀏覽:486
android網路mp3格式 瀏覽:321
程序員抱怨it氣氛 瀏覽:698
改apk伺服器地址 瀏覽:414
原理圖中的編譯 瀏覽:924
繽智怎麼給車機安裝app 瀏覽:728
伺服器的證件是什麼 瀏覽:538
linuxgraphics 瀏覽:137
ACPI編譯工具MaciASL 瀏覽:895
導線點加密技巧 瀏覽:103
閃迪加密軟體如何去除 瀏覽:560