タグ:javaの、トラブルシューティング、監視、btrace
一つの文にまとめた:
BTrace
、あなたが前提のアプリケーション検出コード操作でアプリケーションコード、ノンストップサービスを変更して、問題を診断することなく、それが生産環境に不可欠な強力なJavaのオンラインアプリケーション検出ツール(ダイナミック追跡ツール)であることができていますアーティファクト、この記事では、その使用について説明します。
1はじめに
BTrace
それは、オープンソースソフトウェア、github
アドレス:https://github.com/btraceio/btrace
ある公式サイトを紹介しBTrace is a safe, dynamic tracing tool for the Java platform.
、それが動的にバイトコードの目標追跡アプリケーションにコードを挿入することができ、動的追跡ツールのJavaアプリケーションに安全です、。ダイナミックとは何ですか?我々は、すべてのJavaアプリケーションの起動がいつことを知っているclass
ために、ファイルのロードJVM
を実行し、このタイムclass
コード機能は、コードを変更するために、(変更しない)、静的なだけで、展開、再コンパイルを開始、変更することができるかを決定することです。
オンラインアプリケーションを扱うときと、私たちはしばしば、コードの動作を見てパラメータ値を必要とする、本番環境で表示したり、などのデバッグログに独自の必要性を追加し、開発段階で、ログを追加し、問題なく再起動しますが、ないに戻り(本番環境は、一般的にサービスを停止することは容易ではない、とでも再開することができ、問題が問題を再現することができませんでしオンサイトの破壊を、発生する可能性があります)を適用し、その方法は、実行するJavaアプリケーションの中に存在する場合、プログラムを再起動せずに、ダイナミックに追加私は、コンテンツの(トラック)を監視したいですか?Btrace
そのようなアーティファクトは、動的追跡場合に再起動せずにアプリケーションの動作を監視することができ、プログラムデータは、実行時、メソッドパラメータ、戻り値、グローバル変数で取得した情報をスタックすることができるされています。この記事では、のためにあるBTrace
動作や原理の使用について説明します。
2 BTrace動作原理
動的2.1クラスファイルを置き換える修正
BTrace
達成するためのJavaベースの動的トラッキング技術です。Java開発者のために、Javaプログラムの開発プロセスは明らかに、Javaコードを記述したクラスファイルのためにそれをコンパイルして、しているJVM
ロードされたクラスを実行します。あなたがアプリケーションを停止せずに、この時間をしたい場合はclass
、このような方法のように、コンテンツを追加するように変更トラックを(method
主に二つのことを、出力を追加します):
- (1)変更がにロードされている
JVM
カスタムの出力を追加し、クラス - JVM`で実行クラスの(2)の交換
最初のステップは、原因に、修正JVM
直接バイトコード変更されていない、すべてのクラスファイルの操作class
ライン(もちろん、読み込み可能なバイトコードファイルのJavaコードがはるかに高くなっている)上のファイルを、すでに対応するフレームワークがあります私たちは、これがすることです行うことができASM
、このフレームワークを使用し、直接など、それはまた、動的に新しいクラスを作成している私たちは簡単に変更するクラスを注入することによって、バイトコードファイルを操作することを可能にするインターフェースを提供し、フレームのバイトコードを編集することができますように。Spring
これは、動的プロキシを達成するために、この技術を使用することです。
第二段階、交換してください、あなたが提供されているJavaを使用する必要がある場合は交換しjava.lang.instrument.Instrumentation
、それは2つのインタフェースを有しているredefineClasses
とretransformClasses
、redefineClasses
既存のファイルを置き換えるために、独自のクラスのバイトコードファイルを提供、retransformClasses
すでに存在するバイトコード変更し、ファイルを置き換えます。しかし、それは、と指摘するinstrument
(など、追加、変更、フィールドやメソッドは、メソッドのシグネチャを変更していない削除、継承されたプロパティを変更することはできません)の使用が制限されました:
The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance
复制代码
実行中のプロセスを2.2 BTraceモジュール
BTraceは、物品、達成するために、以前の技術に基づいており、「Javaの動的トラッキング技術の照会」()https://mp.weixin.qq.com/s/_hSaI5yMvPTWxvFgl-UItA
以下に簡単に説明し、ダイナミックトラッキング技術については詳細に記載されています。
メインモジュール2.2.1
-
BTraceスクリプト:必要に応じてBTrace定義されたアノテーションを使用し、我々は簡単にスクリプトを開発することができます。
-
コンパイラ:BTraceクラスファイルにコンパイルBTraceスクリプト。
-
クライアント:クラスのエージェントにファイルを送信します。
-
エージェントは:Javaベース
Attach API
-実行中のエージェント、動的に取り付けることができるJVM
上、その後のターンはBTrace Server
、スクリプトを解析して、スクリプトベースのルールに従って変更されることが判明、バイトコードの呼び出しを変更し、送信し、クライアントスクリプトBTraceを受けインタフェースは、オブジェクトの動作に影響を取り、修正を行います。Java Instrument
retransform
2.2.2実行プロセス
以下のフローチャートを実行します。
Javaソースコードのように、あなたの書くBtrace
スクリプト(また、Javaファイルを)、(コンパイルcompiler
)、クライアントから送信されたagent
、agent
によって、attach api
JVMに追加し始めるagent server
受信するclient
コンテンツは、底が使用され、オーバー送られたASM
修正バイトコードファイルを、次に使用するインタフェースを代わりに変更されたクラスファイル、出力を通じて実行した後に送られたディスプレイ。Java Instrument
retransform
agent
client
3 BTraceインストール
知っているBTrace
動作の原理を、インストール慣行は今見ることができます。まだこの論文の例java-monitor-example
。BTrace
インストールは、箱から出して、非常に簡単です。
- ダウンロード(現在のバージョンです
[v1.3.11.3]
):https://github.com/btraceio/btrace/releases
- Javaアプリケーションサーバーを抽出するために、どこで監視します
btrace
でコマンドbin
ディレクトリ- あなたが任意のディレクトリで実行する必要がある場合は、する必要があります
btrace
(環境変数を設定しますexport
)
4つのBTraceアプリケーションシナリオ
基本的に、BTrace
それが有する前述れるなど、継承、変更、削除方法は、プロパティを追加することができない、唯一の出力ダイナミック・トラッキング・クラスに適用されるInstrument
制限は、同じです。一般的に、使用Btrace
のいくつかに基づいて、シーンの大部分を含んで、クラスのログ出力に属し、オンライン監視アプリケーションのために:
- 一つのプロセスパラメータと戻り値に参照してください。
- 特定のメソッドの応答時間を確認してください
- 実行するコードの行があるかどうかを参照してください。
- 印刷システムのパラメータ、またはJVMの起動パラメータ
- 印刷方法は、スレッドのスタックを呼び出します
- 例外が発生した場合に異常情報を印刷
5 BTraceの使用
Btrace
スタンドアロンツールとして、デフォルトではローカルでのみ実行することができ、それは言うことです、あなたはJavaアプリケーションがモニターを実行したいものは、対応するサーバーにそれを解凍する必要があります。この例では実行されjava-monitor-example
、スクリプトを記述し、出力を参照するには、スクリプトを実行して、Javaアプリケーションを監視する必要があるとして、および監視は、ビジネスニーズに基づいています。
5.1スクリプティング
5.1.1ノートとBTraceUtils
Btrace
Javaのスクリプトやコードを書くには違いはありませんが、多くの比較的単純な、主に使用してBtrace
提供されたアノテーションをしてBTraceUtils
、注釈を伝えるために使用されBtrace
、場所を傍受する傍受するクラスの必要性と遮断機会をBTraceUtils
情報機能のプリントアウトの種類を提供するため。次の例では、公式サイトを与えられます:
package samples;
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
/**
* This script traces method entry into every method of
* every class in javax.swing package! Think before using
* this script -- this will slow down your app significantly!!
*/
@BTrace public class AllMethods {
@OnMethod(
clazz="/javax\\.swing\\..*/",
method="/.*/"
)
public static void m(@ProbeClassName String probeClass, @ProbeMethodName String probeMethod) {
print(Strings.strcat("entered ", probeClass));
println(Strings.strcat(".", probeMethod));
}
}
复制代码
上記のコードは、すべて傍受の呼び出しと言ったjavax.swing
方法の始まり、その後は、クラス名やメソッド名をプリントアウト。注釈があることに留意することができ@BTrace
、@OnMethod
、@ProbeClassName
、@ProbeMethodName
、むしろprint
、println
それはBTraceUtils
静的な方法を提供します。BTraceUtils
これは、多くの印刷方法(例は後述する)を提供します。また、トラッキング動作は静的メソッドの本体を指定する必要があることに注意し、したがってする必要がstatic
近づきます。
また、に関してBTrace
の参照を提供ノートかもしれ公式文書(https://github.com/btraceio/btrace/wiki/BTrace-Annotations
)。次のものがあります。
/**Class Annotations*/
@com.sun.btrace.annotations.DTrace
@com.sun.btrace.annotations.DTraceRef
@com.sun.btrace.annotations.BTrace
/**Method Annotations*/
@com.sun.btrace.annotations.OnMethod
@com.sun.btrace.annotations.OnTimer
@com.sun.btrace.annotations.OnError
@com.sun.btrace.annotations.OnExit
@com.sun.btrace.annotations.OnEvent
@com.sun.btrace.annotations.OnLowMemory
@com.sun.btrace.annotations.OnProbe
/**Argument Annotations*/
@com.sun.btrace.annotations.Self
@com.sun.btrace.annotations.Return
@com.sun.btrace.annotations.CalledInstance
@com.sun.btrace.annotations.CalledMethod
/**Field Annotations*/
@com.sun.btrace.annotations.Export
@com.sun.btrace.annotations.Property
@com.sun.btrace.annotations.TLS
复制代码
これは、@OnMethod
より多くのと、主に3つのプロパティであることを説明することが重要であるclazz
、method
とlocation
。
-
clazz
次のようなクラスのフル・パス名、me.mason.monitor.controller.UserController
-
method
:のような、メソッド名を監視するにはgetUsers
-
location
:使用する傍受機会@Location
注釈を。
@Location
以下があります。
Kind.ENTRY
:メソッドに入ると呼び出しKind.RETURN
:メソッドを呼び出す終了すると、定義された唯一のインターセプト位置Kind.RETURN
方法を得るためには、結果を返し@Return
、実行時間@Duration
Kind.CALL
:他のメソッドの呼び出しを呼び出すときKind.LINE
:指定された場所にコードかどうかを監視するために、ラインを設定することによりKind.ERROR, Kind.THROW, Kind.CATCH
:トラッキング異常事態
書き込みの5.1.2
書くための勧告またはJava Mavenプロジェクトの開発環境を使用するには、コードヒントを使用することができます。そして、サーバを監視するために、対応する必要性に書き込まれました。しかし、あなたは、対応するjarファイルのパッケージ(編集する際に参照する必要があるbtrace-agent
、btrace-boot
、btrace-client
ダウンロードしたインストール中のjar対応)、build
ディレクトリを。pom.xml
導入それは使用することができます。次のように:
<!-- BTrace -->
<dependency>
<groupId>com.sun.btrace</groupId>
<artifactId>btrace-agent</artifactId>
<version>1.3.11.3</version>
<type>jar</type>
<scope>system</scope>
<systemPath>E:/btrace-bin-1.3.11.3/build/btrace-agent.jar</systemPath>
</dependency>
<dependency>
<groupId>com.sun.btrace</groupId>
<artifactId>btrace-boot</artifactId>
<version>1.3.11.3</version>
<type>jar</type>
<scope>system</scope>
<systemPath>E:/btrace-bin-1.3.11.3/build/btrace-boot.jar</systemPath>
</dependency>
<dependency>
<groupId>com.sun.btrace</groupId>
<artifactId>btrace-client</artifactId>
<version>1.3.11.3</version>
<type>jar</type>
<scope>system</scope>
<systemPath>E:/btrace-bin-1.3.11.3/build/btrace-client.jar</systemPath>
</dependency>
复制代码
5.2スクリプト
印刷ヘルプ情報は次のとおりです。
一般的には、サーバ上で、直接IS btrace PID btraceFile.java
、出力(出力のようなファイルの内容を、次いでを見ることができる見てbtrace PID btraceFile.java > info.txt
)。あなたが特定のjarファイルパッケージを使用している場合は、パラメータに置く必要があるcp
かclasspath
プラス。以下の例では、メソッド呼び出しが値出力を返しています。
5.3スクリプト例
説明するために、いくつかの一般的な例に従うことによりBTrace
、スクリプトの使用、例えば、プロジェクト内のスクリプトjava-monitor-example
でbtrace
ディレクトリを。java-monitor-example
それぞれ、Aがcontroller
とservice
、メソッド定義がある、次の動的追跡は、これらの方法に基づいて説明します。
/**
* UserController.java
**/
@GetMapping("/user")
public ResponseResult<User> getUser() {
User user = userService.getUser();
return ResponseResult.ok(user);
}
@GetMapping("/users")
public ResponseResult<User> getUsers(int num) {
List<User> users = userService.getUsers(num);
return ResponseResult.ok(users);
}
/**
* UserService.java
* 根据ID获取用户
*
* @return
*/
public User getUser() {
return mockUser();
}
/**
* 获取用户数组
*
* @return
*/
public List<User> getUsers(int num) {
userList.clear();
for(int i=0 ; i < num; i++){
userList.add(mockUser());
}
return userList;
}
复制代码
5.3.1印刷方法情報
- (メソッド呼び出し時に印刷パラメータを呼び出し
UserController
のgetUsers
印刷をする場合の方法)
@OnMethod(clazz = "me.mason.monitor.controller.UserController"
,method = "getUsers",location = @Location(Kind.ENTRY))
public static void readFunction(@ProbeClassName String className, @ProbeMethodName String methodName, AnyType[] args) {
// 打印时间
BTraceUtils.println(BTraceUtils.Time.timestamp("yyyy-MM-dd HH:mm:ss"));
BTraceUtils.println("method controller");
BTraceUtils.printArray(args);
BTraceUtils.println(className + "," + methodName);
BTraceUtils.println("==========================");
}
复制代码
- 印刷のメソッドを呼び出し、戻り値
@OnMethod(clazz = "me.mason.monitor.service.UserService"
,method = "getUsers",location = @Location(Kind.RETURN))
public static void printReturnData1(@Return AnyType result){
BTraceUtils.println(BTraceUtils.Time.timestamp("yyyy-MM-dd HH:mm:ss"));
BTraceUtils.printFields(result);
BTraceUtils.println("==========================");
BTraceUtils.println(BTraceUtils.str(result));
BTraceUtils.println("==========================");
}
复制代码
- (かどうかを確認するために実行の実装に行数
UserService
行39)
@OnMethod(clazz = "me.mason.monitor.service.UserService"
,method = "getUsers",location = @Location(value = Kind.LINE,line = 39))
public static void printLineData(@ProbeClassName String className, @ProbeMethodName String methodName,int line){
BTraceUtils.println(BTraceUtils.Time.timestamp("yyyy-MM-dd HH:mm:ss"));
BTraceUtils.println(className + "," + methodName + ","+line);
BTraceUtils.println("==========================");
}
复制代码
- ときに使用される方法の実行(長い使用方法)
UserController
getUsers
@OnMethod(clazz = "me.mason.monitor.controller.UserController"
,method = "getUsers",location = @Location(Kind.RETURN))
public static void getUsersDuration(@Duration long duration){
BTraceUtils.println(BTraceUtils.Time.timestamp("yyyy-MM-dd HH:mm:ss"));
BTraceUtils.println("time(ns):" + duration);
BTraceUtils.println("time(ms):" + BTraceUtils.str(duration / 1000000));
BTraceUtils.println("time(s):" + BTraceUtils.str(duration / 1000000000));
BTraceUtils.println("==========================");
}
复制代码
5.3.2 JVM印刷システムのプロパティと属性
同様にJDK
、コマンドラインツールjinfo
、加えて、jmap
そしてjstatck
公式の例で見つけることができます。
@BTrace
public class JInfo {
static {
println("System Properties:");
printProperties();
println("VM Flags:");
printVmArguments();
println("OS Enviroment:");
printEnv();
exit(0);
}
}
复制代码
5.3.3印刷出力異常
java
開発者がいることを知っておくべきjava
異常を分割Error
してException
、彼らがしている間、Throwable
サブカテゴリー、すなわち、java
あるすべての例外の親クラスではThrowable
、このコンストラクタを追跡し、あなたがして、スタックをプリントアウトすることができます。次のように:
//局部变量存储异常
@TLS static Throwable currentException;
//异常构造函数开始
@OnMethod(
clazz="java.lang.Throwable",
method="<init>"
)
public static void onthrow(@Self Throwable self) {
currentException = self;
}
//异常构造函数结束,输出堆栈
@OnMethod(
clazz="java.lang.Throwable",
method="<init>",
location=@Location(Kind.RETURN)
)
public static void onthrowreturn() {
if (currentException != null) {
Threads.jstack(currentException);
println("=====================");
currentException = null;
}
}
复制代码
5.4スクリプトの制限
BTrace
バイトコードが、主に情報の要求出力、及びプログラムの正常な動作に影響を修飾がJVMは、「読み取り専用」、BTraceをそれを行うことです。動的置換クラスファイルので、修飾バイトコードが自動的に復元されていないことに留意されたいです。関係者はまた、文書を記述BTrace
スクリプトは次の制限があります。
-
オブジェクトを作成することは許されません
-
配列を作成することはできません
-
例外をスローすることはできません
-
異常をキャッチすることはできません
-
静的メソッドは、呼び出しのcom.sun.btrace.BTraceUtilsが提供のみを許可し、他のオブジェクトやクラスのメソッドを呼び出すことはできません(一部のデータ処理と情報出力手段)
-
クラスのプロパティを変更することはできません
-
メンバ変数やメソッドを許可していない、唯一の静的パブリックvoidメソッドを可能に
-
これは、内部クラス、ネストされたクラスを許可していません
-
この方法は、同期と同期のブロックを許可していません
-
それは循環を許可していません
-
(java.lang.Object上位を除いて、もちろん)他のクラスから継承することはできません。
-
インターフェイスを実装することはできません。
-
許可されていませんアサート
-
Classオブジェクトが許可されていません
6いくつかの経験
- コードヒントを提供するために、スクリプトの開発環境、対応するjarファイルの導入を構築するためにJavaのMavenプロジェクトを使用してください。
- 公式が提供するビューの例は、ダウンロードパッケージ内の位置の例を提供しています
btrace-bin-1.3.11.3\samples
カタログを BTrace
入力パラメータを追跡するスクリプトは、戻り値の型は、複合型を使用することができます直接使用する単純型(たとえば、int型、float型、など)でAnyType
、時間を追加したが、彼らは(Userなど)のカスタムパッケージの種類を使用している場合は、スクリプトを実行する必要がありますcp
かclasspath
パラメータは、カスタムパッケージを指定します。- 通常、単純型または文字列、直接
print
またはprintln
、オブジェクトのプロパティは、印刷するために使用され得るprintFields
、印刷List
、使用することができますBTraceUtils.println(BTraceUtils.str(list))
- プローブ法に最後の行で分離されたプリントが、それを強くお勧めします。出力は分離されていない場合、分離されていないコンテンツ後の出力または出力がない場合があり、出力バッファ遅延に起因するがあってもよいです。パーティションを使用することができます
BTraceUtils.println
かBTraceUtils.println("============")
。
7概要
あなたが問題を診断するためにノンストップサービスのログ出力をしたい場合は、オンラインでのJavaアプリケーションについては、ダイナミックトラッキング技術は必要不可欠な技術である、とBtrace
の強力なツールを追跡する動的な達成するために、この技術を使用しています。以下からのBtrace
動作原理、インストール、アプリケーションのシナリオ、スクリプト、実行し、その詳細な説明、の側面は、あなたが深めしたいと考えてBtrace
、オンラインの問題を解決するために、より便利で効率的な、理解を。
データシート
BTrace
公式サイト:https://github.com/btraceio/btrace
BTrace
注意:https://github.com/btraceio/btrace/wiki/BTrace-Annotations
- サンプルコード住所:
https://github.com/mianshenglee/my-example/tree/master/java-monitor-example
- 探索するためのJavaの動的トラッキング技術:
https://mp.weixin.qq.com/s/_hSaI5yMvPTWxvFgl-UItA
- BTrace原理に:
https://www.rowkey.me/blog/2016/09/20/btrace/