NetBeans IDE 4.1/5.0 Profiler 教程
本文旨在介紹配合使用 NetBeans Profiler v5.0 或 Profiler Milestone 8 的內(nèi)容。如果您使用的是 Milestone 5,請使用此版本。如果您使用的是 Milestone 6,請使用此版本。
預(yù)計持續(xù)時間:50 分鐘
NetBeans Profiler 是一個功能強大的工具,它提供了有關(guān)應(yīng)用程序運行時行為的重要信息。NetBeans Profiler 產(chǎn)生的開銷相對來說較小,它可以跟蹤線程狀態(tài)、CPU 性能和內(nèi)存使用情況。本教程將向您介紹如何使用 NetBeans Profiler 來完成以下操作:
- 監(jiān)視應(yīng)用程序的運行時行為,其中包括:
- 堆內(nèi)存大小
- 垃圾回收統(tǒng)計信息
- 線程計數(shù)
- 線程狀態(tài):運行、休眠、等待、受阻
- 確定應(yīng)用程序方法使用的 CPU 時間
- 監(jiān)視應(yīng)用程序創(chuàng)建對象的過程
先決條件
本教程假定您已經(jīng)具有了一些基本的 Java 編程和 NetBeans IDE 使用經(jīng)驗。
教程所需的軟件:
- 下載并安裝 Java 2 Platform Standard Edition v5.0, Update 4(或更高版本)。請注意,NetBeans IDE 需要完整的 JDK,而不僅僅是 JRE。請記錄此安裝目錄。
- 下載并安裝 NetBeans IDE v4.1 或 v5.0。請記錄此安裝目錄。當系統(tǒng)提示您選擇 JDK 時,請指定 v5.0, Update 4(或更高版本的)JDK。
- 下載并安裝用于 NetBeans IDE v5.0 的 NetBeans Profiler v5.0。如果使用的是 NetBeans IDE 4.1,請下載 Milestone 8。
Profiler 安裝程序會要求您修改 NetBeans IDE 安裝;請指定用于 NetBeans IDE 的安裝目錄。
注意:Profiler v5.0 只能與 NetBeans IDE v5.0 一起使用;而 Profiler Milestone 8 只能與 NetBeans IDE v4.1 一起使用。 - 下載教程 zip 文件,其中包括練習中使用的項目。
本文使用的表示法
- <NETBEANS_HOME> - NetBeans IDE 安裝目錄
- <USER_HOME> - 用戶的 home 目錄
- <tutorial_root> - 解壓縮教程 zip 文件所在的目錄
- 本文使用 <tutorial_root> 來表示解壓縮此教程的 zip 文件所在的目錄。此教程的 zip 文件的名稱為 profilertutorial.zip。
- 將教程 zip 文件解壓縮到 <tutorial_root> 目錄時,系統(tǒng)會創(chuàng)建一個名為 netbeansprofiler 的子目錄。例如,在 Windows 操作系統(tǒng)中,如果已將教程 zip 文件解壓縮到驅(qū)動器 E:\ 的根目錄中,則系統(tǒng)會創(chuàng)建 E:\netbeansprofiler 子目錄。在 Solaris/Linux 操作系統(tǒng)中,如果已將教程 zip 文件解壓縮到 /home/username 目錄中,則系統(tǒng)會創(chuàng)建 /home/username/netbeansprofiler 子目錄。
教程練習
- 練習 0:安裝并配置教程環(huán)境
- 練習 1:監(jiān)視 Swing 應(yīng)用程序中的線程狀態(tài)
- 練習 2:確定某個方法使用的 CPU 時間(15 分鐘)
- 練習 3:分析對象創(chuàng)建過程以查找內(nèi)存泄漏
參考資源:
練習 0:安裝并配置教程環(huán)境
在開始學(xué)習教程之前,請先檢查以下內(nèi)容:
- 啟動 NetBeans IDE,并確認 IDE 已打開。通過選擇“性能分析”>“幫助”>“關(guān)于性能分析器...”,驗證安是否裝了 NetBeans Profiler。
- 在 Windows 操作系統(tǒng)中,雙擊 NetBeans IDE 圖標
- 在 Solaris/Linux 操作系統(tǒng)中,打開終端窗口,然后鍵入 <NETBEANS_HOME>/bin/netbeans
- 在 Windows 操作系統(tǒng)中,雙擊 NetBeans IDE 圖標
- 僅限 NetBeans IDE v4.1:安裝所需的修補程序。
- 從“工具”菜單中選擇“更新中心”,以訪問 NetBeans 更新中心。
- 確保選中了“NetBeans 修補程序更新中心”,然后單擊“下一步”按鈕。建立連接后,將顯示一個更新列表。
- 在“NetBeans 修補程序更新中心”條目下,選擇“NetBeans Profiler(J2EE 項目 - Tomcat5 支持)”。該操作還將自動選擇 "Tomcat 5 Server" 條目。
- 單擊“下一步”按鈕,并按照說明進行操作以便 IDE 可以安裝這些修補程序。
練習 1:監(jiān)視 Swing 應(yīng)用程序中的線程狀態(tài)(15 分鐘)
本練習的學(xué)習目的:
在本練習中,您將學(xué)習如何使用 NetBeans Profiler 監(jiān)視 J2SE 應(yīng)用程序中的線程狀態(tài)。這樣,您就可以診斷樣例應(yīng)用程序中的性能問題。
背景信息:
Swing 庫為 J2SE 應(yīng)用程序提供了圖形用戶界面組件。Swing 庫會使用到多個線程,利用 NetBeans Profiler 這一功能強大的工具,您可以分析出每個線程所花費的處理時間,從而利用這些分析信息來解決性能問題。
執(zhí)行步驟:
- 選擇“文件”>“打開項目”。找到 <tutorial_root>/netbeansprofiler/exercises 文件夾。選擇 exercise1 文件夾,然后單擊“打開項目文件夾”按鈕。
- 在“項目”窗口中,右鍵單擊 exercise1 條目并選擇“清理并生成項目”。然后,再次右鍵單擊 exercise1 條目并選擇“運行項目”。此時,將顯示該程序的窗口,如下所示。
- 將 "Seconds Before Notification" 設(shè)置為 30。
- 單擊 "Start!" 按鈕。請注意,該程序無法正確地刷新屏幕。
- 單擊 "Exit" 按鈕。請注意,該程序根本不會作出響應(yīng)。
- 將另一個窗口放在該窗口的某一部分上,以遮擋該窗口的視圖。當移開另一個窗口時,您會注意到樣例應(yīng)用程序沒有相應(yīng)地刷新其窗口。如下面的示例所示。
- 30 秒后,最終將顯示一個消息框,如下所示。單擊消息框上的 "OK" 按鈕。
- 應(yīng)用程序窗口將再次開始響應(yīng)。單擊 "Exit" 按鈕將其關(guān)閉。
- 選擇“性能分析”>“分析主項目”。
- 如果出現(xiàn)一個對話框,詢問您是否允許修改項目生成腳本,請單擊“確定”。如下面的示例所示。
- 此時會顯示“選擇性能分析任務(wù)”對話框。單擊占據(jù)較大區(qū)域的“監(jiān)視應(yīng)用程序”按鈕。
- 應(yīng)選中“啟用線程監(jiān)視”復(fù)選框。
- 單擊“運行”按鈕。如果顯示一個對話框,指示您必須先收集 Profiler 的校準信息,請單擊“確定”按鈕。如下面的示例所示。
選擇“性能分析”>“高級命令”>“運行性能分析器校準”。完成校準后,Profiler 會顯示一個對話框,請單擊“確定”按鈕。如下面的示例所示。
要進行性能分析,請返回至上面的第 9 步。
- 完成上述步驟后,將啟動該應(yīng)用程序,并且 IDE 會顯示“性能分析器”控制面板,如下所示。
- 性能分析器將在其主窗口中顯示線程狀態(tài),如下面的示例所示。
它使用顏色編碼來顯示線程狀態(tài)。- 綠色:線程正在運行或準備運行。
- 紫色:線程正在調(diào)用 Thread.sleep(),處于休眠狀態(tài)。
- 黃色:線程正在調(diào)用 Object.wait(),處于等待狀態(tài)。
- 紅色:線程在嘗試訪問同步的塊或方法時受阻。
- 找到樣例 Swing 應(yīng)用程序的窗口(NetBeans IDE 窗口可能在其上面)。單擊樣例應(yīng)用程序中的 "Start!" 按鈕,同時監(jiān)視標記為 AWT-EventQueue-0 的線程所發(fā)生的變化。它將變?yōu)榫G色并持續(xù)這種狀態(tài)整整 30 秒鐘,如以下樣例所示。
此圖形顯示了應(yīng)用程序沒有響應(yīng)的原因。標記為 AWT-EventQueue-0 的線程是 Swing 用來處理窗口事件的事件分發(fā)線程 (Event Dispatch Thread, EDT)。在正常運行的 Swing 應(yīng)用程序中,EDT 的大部分時間處于等待狀態(tài)而運行的時間卻很少,因為它只有在分發(fā)事件時才會運行很短的一段時間。但是,如果應(yīng)用程序中的事件處理程序未立即返回,則程序?qū)⑼V鬼憫?yīng),就像在此示例中一樣。
- 30 秒后,屏幕將顯示應(yīng)用程序的消息框。找到該消息框(NetBeans IDE 窗口可能在其上面)并單擊 "OK" 按鈕。然后,單擊樣例應(yīng)用程序的 "Exit" 按鈕,將其關(guān)閉。
- “項目”窗口與“性能分析器”控制面板共享同一個空間;單擊“項目”標簽將會顯示“項目”窗口。
- 在“項目”窗口中,雙擊 exercise1 條目以將其展開,然后展開“源包”和 profilingthreads 條目。右鍵單擊 DisplayForm.java 條目并選擇“打開”。
- 在包含 DisplayForm.java 的編輯器窗口中,取消第 132 行至第 157 行的代碼塊注釋。提示:如果未將編輯器配置為顯示行號,請選擇“視圖”>“顯示行號”。
- 在包含 DisplayForm.java 的編輯器窗口中,取消(或注釋掉)第 122 行到第 128 行的代碼塊注釋。下圖突出顯示了取消注釋的代碼塊。
- 選擇“文件”>“保存”。您剛才刪除了未正確使用 EDT 的代碼,并利用了更穩(wěn)定可靠的解決方案來替代它。現(xiàn)在,應(yīng)用程序可以及時地作出響應(yīng)。
- 選擇“生成”>“生成主項目”(或按 F11 鍵)。
- 選擇“性能分析”>“分析主項目”。
- 將顯示“選擇性能分析任務(wù)”對話框。單擊占據(jù)較大區(qū)域的“監(jiān)視應(yīng)用程序”按鈕。
- 確保選中了“啟用線程監(jiān)視”。
- 單擊“運行”按鈕。
- 在顯示樣例程序時,單擊 "Start!" 按鈕。請注意,此時的性能分析線程圖已經(jīng)發(fā)生了變化,如以下示例所示。
EDT 為黃色,應(yīng)用程序創(chuàng)建的名為 "Our SwingWorker #1" 的線程為綠色。由于 EDT 不是用來執(zhí)行耗時任務(wù)的,因此,按鈕和其他程序控件仍保持響應(yīng)的狀態(tài)。
- 在樣例程序中單擊 "Exit"。
- 右鍵單擊 Profiler 圖形中的 AWT-EventQueue-0 線程,然后選擇“線程詳細信息”。Profiler 會顯示一個餅圖,表明了每種狀態(tài)所花的時間;如以下示例所示。
該圖形可以幫助您判斷程序在每個線程中所花費的時間是否恰當。上述示例是代碼修復(fù)后的示例,因此,它顯示了 EDT 在大部分時間中都處于等待狀態(tài)的情形,這正好是該線程應(yīng)具有的行為。
- 在“項目”窗口中,右鍵單擊 exercise1 條目,然后選擇“關(guān)閉項目”。
小結(jié):
在本練習中,您學(xué)習了如何使用 Profiler 來啟動應(yīng)用程序,以及如何解釋 Profiler 的線程信息圖形,以此來跟蹤 Swing 應(yīng)用程序中的性能問題。
練習 2:確定某個方法使用的 CPU 時間(15 分鐘)
本練習的學(xué)習目的:
在本練習中,您將學(xué)習如何使用 Profiler 來確定某個應(yīng)用程序的方法所花費的時間。
背景信息:
CPU 的性能問題通常與應(yīng)用程序的特定功能有關(guān)。例如,在報告系統(tǒng)中,某個報告的運行速度可能比其他報告慢。只分析應(yīng)用程序中出現(xiàn)性能問題的部分,可以大大減少性能分析器產(chǎn)生的開銷。在本練習中,您將使用 NetBeans Profiler 來檢查 Web 應(yīng)用程序中 CPU 的使用情況。在練習 3 中,我們?nèi)匀皇褂迷摌永?Web 應(yīng)用程序來說明如何通過 Profiler 查找內(nèi)存泄漏。
執(zhí)行步驟:
- 選擇“文件”>“打開項目”。找到 <tutorial_root>/netbeansprofiler/exercises 文件夾。選擇 exercise2 文件夾,并確保選中“作為主項目打開”。單擊“打開項目文件夾”按鈕。
- 在“項目”窗口中,單擊 exercise2 條目,然后從菜單中選擇“生成”>“清理并生成主項目”。
- 從菜單中選擇“性能分析”>“分析主項目”。如果出現(xiàn)一個對話框,詢問您是否允許修改項目生成腳本,請單擊“確定”。
- 將顯示“選擇性能分析任務(wù)”對話框。
- 單擊“分析性能”按鈕。
- 選擇“部分應(yīng)用程序”單選按鈕。然后,單擊位于“部分應(yīng)用程序”單選按鈕旁邊的“選擇”按鈕。此時將顯示“指定根方法”窗口。
注意:下面的三個步驟僅適用于 Milestone 8。
- 在“指定根方法”窗口中,單擊“從項目添加...”按鈕以添加要分析的根方法。將會顯示“選擇方法”窗口。
- 在“選擇方法”窗口中,單擊“選擇”按鈕。Profiler 將顯示“選擇類”窗口。
- 在“類名”文本字段中輸入
Per
。等待 IDE 為您顯示適用的類列表。選擇 Performance 類。單擊“打開”按鈕以打開其方法列表。注意:下面的兩個步驟只適用于 Profiler v5.0。
- 在“指定根方法”窗口中,單擊“從項目添加...”按鈕以添加要分析的根方法。將會顯示“選擇方法”窗口。
- 在“類名”文本字段中,鍵入 demo.Performance,然后按 Enter 鍵。
- 在根方法列表中單擊 processRequest 方法以將其選中,然后單擊“確定”按鈕。您剛才已將 demo.Performance.processRequest 選中為性能分析的根方法。這意味著,性能分析器將分析 demo.Performance.processRequest 方法和它調(diào)用的所有方法,以及這些方法又調(diào)用的所有方法,依此類推。性能分析器將從 demo.Performance.processRequest 開始,通過分析方法調(diào)用圖形來確定哪些方法需要分析。它將只分析那些需要分析的方法,應(yīng)用程序的其余部分將在沒有任何性能分析開銷的情況下繼續(xù)以最快的速度運行。
- 在“指定根方法”窗口中單擊“確定”按鈕。
- 在“分析性能”窗口中,從過濾器列表中選擇“快速過濾器”,然后單擊位于“快速過濾器”條目旁邊的 "..." 按鈕以指定不進行分析的方法。將顯示“設(shè)置快速過濾器”窗口。驗證是否已選中了“排除”單選按鈕。然后,在“過濾器值”文本字段中輸入 org.apache 并單擊“確定”按鈕。這樣,性能分析器將不分析所有 org.apache 包(及其子包)中的方法,即使這些方法被選定的根方法調(diào)用也是如此。這會減少性能分析的開銷,并過濾掉無關(guān)的信息。
- 在“選擇性能分析任務(wù)”窗口中,單擊“運行”按鈕。如果出現(xiàn)一個對話框,要求您提供校準信息,請單擊“確定”按鈕;在性能分析器顯示的對話框說明校準已完成后,請單擊該對話框的“確定”按鈕。
- IDE 將啟動 Tomcat,并在 Web 瀏覽器窗口中顯示 Web 應(yīng)用程序的 index.jsp 頁。同時,將在后臺運行性能分析器。注意:缺省情況下,將在成為焦點的瀏覽器窗口中顯示 index.jsp 頁;您可能需要打開另一個瀏覽器窗口,以便在運行 Web 應(yīng)用程序時可以閱讀這些說明。
- 因為已選擇了 demo.Performance.processRequest 作為根方法,所以,您需要使用導(dǎo)致該根方法運行的 Web 應(yīng)用程序部分:在 Web 瀏覽器中,單擊“性能問題”以轉(zhuǎn)至“性能”演示頁。在“性能”演示頁上的輸入文本字段中輸入 123456。請不要選中“已優(yōu)化”選項。單擊“提交查詢”按鈕,計算小于或等于 123456 的最大素數(shù)。
- 需要幾秒鐘的時間才能出現(xiàn)響應(yīng),這是因為計算最大素數(shù)的算法存在一些性能問題,同時,在監(jiān)視 processRequest 方法的性能時,性能分析器也會產(chǎn)生一些開銷。
- 當瀏覽器中顯示 "123449" 結(jié)果后,請單擊
按鈕,或者選擇“性能分析”>“生成收集結(jié)果的快照”。單擊位于 CPU 使用情況快照底部的“組合”標簽。性能分析器將顯示最新的性能結(jié)果,如下所示。
頂部窗口顯示了從根方法開始的完整方法調(diào)用圖形。底部窗口是重點描述的部分;它顯示了應(yīng)用程序中的熱點,即執(zhí)行時間最長的那些方法。
- 要查看并解釋這些結(jié)果,請注意 processRequest 方法總共運行的時間為 4308 毫秒 (ms)。然而您會發(fā)現(xiàn),運行 processRequest 方法本身的指令只花費了很少的時間,processRequest 的“自用時間”僅為 10.1 毫秒。絕大部分時間花在了 processRequest 調(diào)用的其他方法上。底部窗口中顯示的熱點是按“自用時間”進行排序的。通過查看該列表,您可以看到 calculate 方法占用了 97.8% 的執(zhí)行時間。考慮到為 calculate 方法分配的工作量,這就不足為奇了。
- 為了幫助您確定如何優(yōu)化應(yīng)用程序,NetBeans Profiler 可以識別代碼中無法預(yù)料的瓶頸,或者識別妨礙應(yīng)用程序隨意縮放的瓶頸。單擊熱點列表中的 calculate 條目以了解時間究竟花在什么地方,這會更新調(diào)用圖形窗口以顯示 calculate。因為 calculate 方法不調(diào)用任何其他方法,所以請右鍵單擊 calculate 條目,然后選擇“轉(zhuǎn)至源代碼”以便檢查源代碼。您會發(fā)現(xiàn)它使用了效率很低的算法,所以應(yīng)該重新設(shè)計這種算法。
- 選擇“性能分析”>“重置收集的結(jié)果”以清除性能分析器的緩沖區(qū)。要將 calculate 的運行時與優(yōu)化的算法 calculate2 作比較,請在 Web 瀏覽器中選中“已優(yōu)化”選項,然后單擊“提交查詢”。等待顯示結(jié)果,然后重新選擇“性能分析”>“生成收集結(jié)果的快照”。請注意,processRequest 方法只運行了 107 毫秒,而 calculate2 方法所花的時間還不到執(zhí)行時間的 10%!
- 注意:我們將繼續(xù)在本練習的基礎(chǔ)上進行下面的練習,因此,請不要關(guān)閉任何窗口。
小結(jié):
在本練習中,您學(xué)習了如何使用性能分析器執(zhí)行方法性能分析。
練習 3:分析對象創(chuàng)建過程以查找內(nèi)存泄漏(20 分鐘)
本練習的學(xué)習目的:
作為練習 2 的后續(xù)練習,我們將在本練習中學(xué)習如何解釋某些性能分析器的圖形以監(jiān)視應(yīng)用程序創(chuàng)建對象的過程。下面將顯示一個內(nèi)存泄漏示例。
執(zhí)行步驟:
- 本練習是在練習 2 的基礎(chǔ)上進行的,因此,請務(wù)必遵循練習 2 中的步驟。
- 從菜單中選擇“性能分析”>“分析主項目”。如果出現(xiàn)一個對話框,詢問您是否要停止當前的性能分析器進程以啟動新進程(如下所示),請單擊“是”按鈕繼續(xù)執(zhí)行。
將顯示“選擇性能分析任務(wù)”對話框。
- 在“選擇性能分析任務(wù)”對話框中,單擊占據(jù)較大區(qū)域的“監(jiān)視應(yīng)用程序”按鈕。
- 單擊“運行”按鈕。IDE 將會在左側(cè)顯示“性能分析器”控制臺。單擊
按鈕,或者選擇“性能分析”>“視圖”>“遙測概覽”。NetBeans Profiler 將在底部的輸出窗口中顯示三個圖形,如下所示。
在左側(cè)的圖形中,紅色的陰影部分表示分配的 JVM 堆大小。紫色的覆蓋部分表示實際使用的堆空間大小。在上面的示例中,上次更新所分配的堆大小已超過了 20 MB。其中,實際用來保存 Java 對象的堆大小略大于 10 MB。
右側(cè)圖形顯示了 JVM 中的活動線程數(shù)。
中間的圖形顯示了兩種重要的堆統(tǒng)計信息。
- 藍線是 JVM 執(zhí)行垃圾回收的時間占執(zhí)行時間的百分比,它是以圖形右側(cè)上的 Y 軸為參照繪制的。JVM 執(zhí)行垃圾回收所花的時間不能用來運行應(yīng)用程序。因此,如果藍線占據(jù)較大的百分比,則需要考慮調(diào)整 JVM,方法是:配置更大的堆大小(請參閱 -Xmx 參數(shù)文檔),或者轉(zhuǎn)換到不同的垃圾回收算法中。
- 紅線表示存活的生成數(shù),它是以圖形左側(cè)的 Y 軸為參照進行繪制的。存活生成數(shù)是指 JVM 堆上所有 Java 對象不同生存期的數(shù)量,其中“生存期”被定義為對象存活時的垃圾回收次數(shù)。如果存活生成數(shù)的值較小,則表明堆上的大部分對象的存活時間基本相同。但是,如果存活生成數(shù)的值隨著時間的變化而增長到一個很高的比率,則表明應(yīng)用程序正在分配新的對象,同時保持對已分配的多個舊對象的引用。如果實際上不再需要這些舊對象,則應(yīng)用程序正在浪費(或“泄漏”)內(nèi)存。
- 藍線是 JVM 執(zhí)行垃圾回收的時間占執(zhí)行時間的百分比,它是以圖形右側(cè)上的 Y 軸為參照繪制的。JVM 執(zhí)行垃圾回收所花的時間不能用來運行應(yīng)用程序。因此,如果藍線占據(jù)較大的百分比,則需要考慮調(diào)整 JVM,方法是:配置更大的堆大小(請參閱 -Xmx 參數(shù)文檔),或者轉(zhuǎn)換到不同的垃圾回收算法中。
- 性能分析器可以對 CPU 性能或內(nèi)存使用情況進行詳細的分析,但不能同時進行這兩種分析。要了解有關(guān)在 JVM 堆上分配對象以及執(zhí)行對象的垃圾回收的詳細信息,請修改性能分析器的設(shè)置。單擊
按鈕,或者選擇“性能分析”>“修改性能分析”。
- 單擊“分析內(nèi)存使用情況”按鈕。
- 選擇“記錄對象創(chuàng)建和垃圾回收”單選按鈕。
- 選中“記錄分配的棧跟蹤”復(fù)選框。
- 單擊“確定”按鈕。
- 現(xiàn)在,您已經(jīng)選擇了分析內(nèi)存使用情況,您需要運行應(yīng)用程序以確定它是否有效地使用了內(nèi)存。單擊“內(nèi)存泄漏”以轉(zhuǎn)至 MemoryLeak 演示頁。
- 在 MemoryLeak 演示頁上,單擊“開始泄漏”。
- 請注意存活生成數(shù)圖形中的峰值,如以下示例所示。這表明可能出現(xiàn)了內(nèi)存泄漏。
- 選擇“性能分析”>“視圖”>“實時結(jié)果”。Profiler 將顯示 JVM 堆中分配的對象的動態(tài)視圖。缺省情況下,它將按每個類的所有實例使用的字節(jié)數(shù)進行排序。由于懷疑可能出現(xiàn)了內(nèi)存泄漏,因此,請單擊“生成數(shù)”列,按每個類的不同對象生存期數(shù)量對顯示結(jié)果進行排序。下面顯示了得到的顯示結(jié)果示例。
- “分配的對象”是性能分析器正在監(jiān)視的對象數(shù)。在本示例中,共監(jiān)視了 38 個 float[] 實例。缺省情況下,該數(shù)字約為應(yīng)用程序?qū)嶋H分配的對象數(shù)的 10%。通過只監(jiān)視已創(chuàng)建對象的一部分,性能分析器可以顯著地減少它在 JVM 中的開銷,這樣,應(yīng)用程序就幾乎可以按最快的速度運行了。
- “活動對象”是仍在 JVM 堆中并因此占用內(nèi)存的已分配對象數(shù)。
- 兩個“活動字節(jié)”列顯示了活動對象所占用的堆內(nèi)存量。一個列顯示圖形,另一個列顯示文本。
- “平均生存期”值是使用活動對象計算的。每個對象的生存期是它存活時的垃圾回收次數(shù)。生存期總和除以活動對象數(shù)得到的結(jié)果就是平均生存期。
- “生成數(shù)”值是使用活動對象計算的。與平均生存期相同,對象生存期是它存活時的垃圾回收次數(shù)。“生成數(shù)”值是活動對象的不同生存期數(shù)量。
- “分配的對象”是性能分析器正在監(jiān)視的對象數(shù)。在本示例中,共監(jiān)視了 38 個 float[] 實例。缺省情況下,該數(shù)字約為應(yīng)用程序?qū)嶋H分配的對象數(shù)的 10%。通過只監(jiān)視已創(chuàng)建對象的一部分,性能分析器可以顯著地減少它在 JVM 中的開銷,這樣,應(yīng)用程序就幾乎可以按最快的速度運行了。
- 隨著程序繼續(xù)運行,性能分析器將更新顯示結(jié)果。請留意 float[] 和 double[] 條目。請注意其生成數(shù)值是如何持續(xù)增加的。結(jié)果是,float[] 和 double[] 在列表中持續(xù)上移。最終,它們會顯示在列表的頂部,緊靠 java.util.HashMap$Entry(其生代數(shù)值也在不斷增加)下面。隨著應(yīng)用程序繼續(xù)運行,java.util.HashMap$Entry、float[] 和 double[] 生成數(shù)值持續(xù)增加,但任何其他類沒有增加。如下面的示例所示。
- 要了解導(dǎo)致生成數(shù)值持續(xù)增加的原因,請選擇“性能分析”>“生成收集結(jié)果的快照”。按生成數(shù)對顯示結(jié)果進行排序。右鍵單擊 double[] 條目,然后選擇“顯示分配棧跟蹤”。性能分析器將顯示所有分配了一個或多個 double[] 對象的方法。如下面的示例所示。
請注意,在分配了 double[] 對象的方法中,只有一個方法創(chuàng)建了具有較大生成數(shù)值的 double[] 對象。該方法是 run(),它位于具有相應(yīng)名稱 demo.memoryleak.LeakThread 的類中。 - 右鍵單擊 run() 方法條目,然后選擇“轉(zhuǎn)至源代碼...”。性能分析器將顯示源代碼,如下所示。
請注意,正在分配 double[] 和 float[] 對象,并隨后將其放在 HashMap 中。但一直并未刪除它們,這意味著,HashMap 保留的引用將會妨礙 JVM 對這些對象進行垃圾回收。這是非常典型的 Java 內(nèi)存泄漏:將對象放在 Map 中,然后就忘記處理它們了。由于本示例中使用的 Map 就是 HashMap,因此,關(guān)聯(lián)的 java.util.HashMap$Entry 對象也出現(xiàn)了泄漏。 - 選擇“性能分析”>“停止”來結(jié)束性能分析會話,或者單擊
按鈕。
- 在“項目”窗口中,選擇 exercise2 條目,然后從菜單中選擇“文件”>“關(guān)閉項目”。
小結(jié):
在本練習中,您學(xué)習了如何使用性能分析器來監(jiān)視應(yīng)用程序創(chuàng)建對象的過程。您還看到了性能分析器在應(yīng)用程序出現(xiàn)內(nèi)存泄漏時所提供的各種類型的分析指數(shù)。