程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> BTrace-一個分析運行中Java程序的簡便工具

BTrace-一個分析運行中Java程序的簡便工具

編輯:關於JAVA
 

有時候你需要分析或者優化你自己的Java程序。最簡單但也是最具侵入性的方式寫一大堆 System.out.println (很明顯這種方式太費勁了)或者使用日志。在添加了許多日志代碼後,你的程序就會由於添加這些代碼變得雜亂無章。

分析優化代碼或者調用方法的性能正是AOP(Aspect Oriented Programming.)關注的重點,使用AOP能夠很優雅的解決這類問題。最主要的是,它允許你在滿足某種條件下調用某種操作而不用修改要被分析的代碼。將切面插入到你代碼的過程叫做“織入”(weaving)。

一共有三種“織入”的方式,並不是每個AOP的實現必須都支持所有的方式。
1.源碼織入(在編譯之前,切面被插入到要分析的代碼中)
2.字節碼織入(切面被插入到編譯之後的.class文件中)
3.動態織入(切面被插入到正在某個JVM中運行的程序中)

順便說一句,你可以使用Java Agents寫一個屬於你自己的簡單的動態織入AOP工具,它能夠在你的所有的代碼執行之前被調用(事實上,Agent方法甚至在你的static void main(String[] args)方法之前被調用)。

內容列表:
1.什麼是BTrace?
2.怎麼才能使用它?
3.示例分析代碼
4.為什麼使用WeakReference?
5.示例BTrace腳本
6.獲取結果
7.調用腳本
8.JStat計數器的訪問
9.通過MBean訪問
10.弱引用與垃圾回收
11.強引用與垃圾回收
12.開銷
13.總結

 

什麼是BTrace?

BTrace是分析你運行中程序的一個有趣的工具。它不侵入你的代碼,並且只會讀取你代碼裡的信息。你可以寫一個與Java代碼完全兼容的腳本來定義你要分析或者監控一個運行中的程序的內容(我認為這與AOP的動態織入是一樣的)。

動態織入的最大優點就是它不需要你重新編譯或者停止你要分析的程序。你只需要像插件一樣把它“插入”你正在運行中的程序中就可以馬上對它進行監控。

怎麼才能使用它

首先,你要運行你要監控的應用(是的,還有種方式是你可以在啟動應用的同時並且監控它,但是你需要到BTrace的網站上詳細了解下)。BTrace可以通過下面三種方式使用:
1.寫一個BTrace腳本,使用命令行btrace(在BTrace的發布版裡帶了)將你的腳本插入到應用裡
2.寫一個BTrace腳本並使用BTrace提供的編譯器編譯
3.使用VisualVM動態的將腳本插入到應用裡

我將通過第三種方式用它,因為我覺得這是最快最簡單的方式。然而,無論你選擇哪種方式jps這個命令你都會用到的。通過jps你能夠知道當前有哪些java進程在運行,它會輸出這些進程的PID,這對其他命令進一步獲取進程信息會很有用。

示例分析代碼

在Github上你能找到我們後面用BTrace腳本分析的完整的示例代碼。代碼很簡單,意圖也很明顯-就是模擬一個緩存的訪問。整個應用包含三個類:

Data.java 它代表將會被存儲在緩存中的數據;用戶可以使用一個鍵獲取到存儲的數據,這個鍵是一個在0-100之間隨機生成的整數。

 



package com.piotrnowicki.btrace;

/**
* Exemplary data that will be stored in the cache. The existence of
* the Data makes sense only with some content; default constructor
* is not provided. Use {@link Data#Data(String)} instead.
*
* @author PiotrNowicki
*
*/
public class Data {

private String content;

public Data(String content) {
this.content = content;
}

public String getContent() {
return content;
}
}
 

DataAccessor.java 是這個應用的關鍵。它保存了緩存(一個通過WeakRefernce指向Data對象的Map),它允許客戶端通過 getData(-)方法取得數據。

如果請求的數據在緩存中,它會獲取這個數據並返回給客戶端;如果緩存沒有這個數據,就會創建一個新的data對象,並把它放到緩存裡然後返回給客戶端。

 


package com.piotrnowicki.btrace;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* This class is responsible for accessing the data stored in
* the cache.
*
* @author PiotrNowicki
*
*/
public class DataAccessor {
private Logger log =
Logger.getLogger(DataAccessor.class.getName());

/**
* The cache for our {@link Data}.
*/
private Map> cache =
new HashMap>();

/**
* Accesses the {@link Data} stored in cache under given
* <code>key</code>. If the data can't be found in the cache, it
* <strong>creates</strong> a new instance of it.
*
* @param key
* for the data we want to fetch.
*
* @return retrieved and cached data.
*/
public Data getData(String key) {
log.log(Level.INFO, "Fetching data by key: {0}", key);

Data result;

WeakReference entry = cache.get(key);

/*
* It's a weak reference, so we need to check if it doesn't
* store a null value.
*/
if (entry != null && entry.get() != null) {
result = entry.get();
} else {
// The content is not important for us for this example.
result = new Data("Randomized content = " + Math.random());

cache.put(key, new WeakReference(result));
}

return result;
}  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved