提高Java開發質量之"內存泄露"
當前,J2EE的 開發 質量 的問題已經越來越突出,如果你的即將上線或已經上線的應用經常不穩定,特別在負載大時尤為明顯,你經常忙于在最后時刻救火,那么應該考慮在開發的早期盡量進行 性能 方面的測試。本文將探討在J2EE開發中,常見的解決辦法,這里以Ques
當前,J2EE的
開發質量的問題已經越來越突出,如果你的即將上線或已經上線的應用經常不穩定,特別在負載大時尤為明顯,你經常忙于在最后時刻救火,那么應該考慮在
開發的早期盡量進行
性能方面的
測試。本文將探討在J2EE開發中,常見的解決辦法,這里以Quest JProbe Suite 工具為例,說明在實際開發中應如何提高開發質量。 "內存泄露"是目前
Java應用中最為常見的問題之一,
單元測試的不完善直接導致生產系統的不穩定。
單元測試是解決"內存泄露"問題的比較適當的環節。這樣可以避免在生產系統中進行冗長煩瑣的搜集數據和分析工作。 "內存泄露"簡單地說,開發人員主觀認為已經不再使用,而實際上在 JVM中仍然被使用的那些對象。往往是由于開發人員的疏忽、架構設計的問題或所使用第三方組件的瑕疵等造成的。 這里我們使用Quest JProbe 來分析一個簡單的
用例。 如下面三圖所示,點擊Add按鈕十次,增加0-9個 Button(如第二圖),然后點擊 Remove按鈕十次,如第三圖。 我們使用JProbe 記錄該過程中內存中對象的變化情況,如下圖: 我們現在將尋找堆中的游離對象-即"內存泄露"對象?;谇懊娴募僭O,你希望Jbutton類的變化數量應該為0即堆中應該沒有Jbutton實例了,因為在上面的試驗中我們最后移走了所有創建的按鈕。實際上,Jbutton對象沒有被移走并且可能繼續游離在堆中。 1. 首先在Instance Summary中查看每個類的Count Change,如果該數據不為0則表示
用例運行完后,JVM堆中該類的實例數發生了變化。因為我們要識別游離對象,就要查看
用例運行完后,JVM堆中的實例數是否發生了變化,也就是在執行時引用的對象到最后是否被釋放。如果用例運行完后,堆中的實例數發生了變化,則說明可能存在游離對象。如果Count Change列沒有顯示出來,右擊Class List,選擇Show/Hide Columns,選中Count Change點擊OK。 2. 在Filter Classes域中輸入*.Jbutton可以快速定位出Jbutton類,因為在上面的試驗中我們主要創建了Jbutton對象,所以我們在這里主要觀察Jbutton類。 3. 我們注意到Jbutton類的Count Change列顯示為+10,這表示從開始運行用例到結束用例運行這段時間內,堆中增加了10個Jbutton對象。盡管我們主觀認為在試驗最后已經銷毀了這十個對象,但實際上它極有可能還存在于堆中。 到這里我們已經識別出堆中很有可能存在游離的對象,下一步我們將進一步定位到類和代碼行。 這部分我們將找到究竟是哪些存活對象還持有Jbutton游離實例的引用。打開Class View窗口查看snapshot中的數據,通過Instance Detail View可以更深入地看到Jbutton的細節信息,最后打開Source窗口我們將看到原來是Jbutton[ ]數組仍然持有游離對象Jbutton。 1. 選中要分析的snapshot,點擊Class View。打開的窗口顯示了堆中的類。 2. 選中Jbutton類并點擊Instance Detail View。這樣可以查看到該類更詳細的信息,包括該類的實例化信息,一共實例化了多少個對象,每個對象都是由誰創建的,對象的調用樹和被調用樹等。 3. 點擊工具條上面的View Only Instance Allocated After Checkpoint。這將移走那些在前面設置斷點后內存中分配的對象,因為我們主要關心的是用例是否存在游離對象,所以不必查看運行用例前內存中的信息,現在你應該只看到十個實例。 4. 選中任意一個Jbutton實例并點擊Memory Leak Doctor,打開Memory Leak Doctor窗口。里面分別用不同顏色表示了對象的創建是在記錄過程前和記錄過程中等兩種情況。游離對象通常在用例運行時即開始記錄后增加的,但可能跟記錄前創建的對象有點聯系。對于這些游離對象,只有一個可能原因。以前存在的LeakExample實例引用Jbutton[ ]了,而Jbutton[ ]則引用了Jbutton實例。 5. 我們模擬在程序中釋放某個引用后,看該引用所關聯的對象是否就可以被垃圾回收,如果可以垃圾回收說明可能存在游離對象。在這里我們看到Jbutton[ ]還持有Jbutton的引用,我們假定Jbutton是游離對象,選中Jbutton[ ]和Jbutton之間的引用,右鍵點擊并且選擇Remove Reference。這時系統將提示如果你在用例的程序中釋放了這個引用,這個實例將被垃圾回收。這只是唯一一個引起游離對象的可能原因。 6. 關閉Memory Leak Doctor窗口。接下來查看分配該實例的方法,并深入該分配方法的代碼,查看該方法最后是否釋放了該實例。 7. 在Instance Detail窗口中,選中Jbutton實例,看Allocated At區域。我們將看到該實例是由方法LeakExample.addButtonToPanel( )分配的。 8. 查看該分配方法的源代碼,右鍵點擊LeakExample.addButtonToPanel行并選中Allocated At Source。 9. 找到用例的源代碼,彈出的窗口顯示選中的addButtonToPanel( )方法并定位到了分配Jbutton實例的代碼行。至此,你看到了按鈕是在什么地方被添加到buttons[ ]數組的了。 10. 在Source窗口中找到removeButtonFromPanel( )方法。我們將注意到執行從button[ ]數組移走按鈕的代碼行嵌在if語句中,實際上,這個條件永遠不能滿足,它自始至終沒有被執行到。這就造成了Jbutton實例一直存在于內存當中,變成了游離對象。(稍后我們可以修改其if的條件或滿足該條件,讓用例可以執行到里面移走Jbutton實例的代碼,這時將看到內存明顯得到改進并且內存中不再存在Jbutton實例) 11. 到這里,我們已經證實button[ ]數組從用例開始運行到結束一直持用Jbutton實例的引用,我們可以肯定內存中存在游離對象。 在運行改進后的用例前,你也可以使用JProbe計算這些游離對象一共消耗多少內存。選中Jbutton實例并從Tree Type下拉列中選擇Reference Tree,這時你將發現Jbutton實例在內存中還引用了很多其它實例。點擊Calculate就可以計算出這些游離對象消耗的內存大小了。
原文轉自:http://www.anti-gravitydesign.com
国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97