BTrace - 1. 소개
BTrace 는 ByteCode Dynamic Trace 의 약자로 DTrace 에 착안을 해서 만들어진 동적 Java process 추적 툴입니다. DTrace 의 개념에 착안해서 만들어진 Java 용 DTrace 라고 생각하시면 이해가 제일 빠르실 겁니다. DTrace 가 생소하신 분들은 sdnkorea blog 의
DTrace Startup Guide 를 먼저 살펴보시기 바랍니다. BTrace 는 현재 jdk6 이상에서만 사용이 가능하며 아직까지는 draft 버전으로 종종 JVM crash 를 유발하기도 합니다. BTrace 는 특정메소드의 호출 혹은 특정 클래스에 관련된 이벤트들을 특수한 코딩이 필요 없이 동적으로 추적할 수 있으므로 현재 실행중인 java process 의 중단 없이 내부를 추적할 수 있는 매우 유용한 툴 입니다.
사용법은 DTrace 와 매우 유사 합니다. DTrace 는 D 언어 스크립트를 현재 실행중인 process 를 target 으로 실행 하듯이 BTrace 는 BTrace 소스(java) 를 실행중인 java process 를 target 으로 실행 합니다.
예)
btrace 4448 AllCall.java (여기서 4448 은 java pid)
프로그램을 추적하려면 어떠한 지점(혹은 이벤트)를 추적할지에 대한 point 설정과 해당 point 에서 필요한 정보를 얻어낼 수 있는 action 코드가 필요할 것입니다. BTrace 스크립트는 사용자가 지정한 probe point (특정 지점 혹은 이벤트로) 에 도달하면 (보통 probe 가 fire 됐다고 표현 합니다) Action 메소드 에서 정의한 코드를 수행합니다. probe point 는 @OnMethod 어노테이션을 이용해서 지정합니다.
지정하는 방법은 Aspectj 의 point-cut 설정과 유사하여 클래스별, 메소드별로 설정할 수 있도록 되어 있습니다.
BTrace 는 현재 실행중인 process 를 추적하기 위한 툴이므로 실행중인 process 에 어떠한 영향도 주어서는 안됩니다. 즉 읽기전용으로 동작해야 된다는 뜻입니다. 그러므로 BTrace 스크립트에서는 오브젝트 생성이나 exception 생성 및 throw, 다른 메소드의 호출등이 불가능 합니다. 이러한 제약조건은 글의 마지막에 정리해 보도록 하겠습니다.
기본적인 개념 설명은 여기서 끝내고 직접 BTrace 스크립트를 보고 설명을 드리도록 하겠습니다.
예제) (BTrace sample 디렉토리의 AllCall1.java)
package com.sun.btrace.samples;
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
/**
* This script demonstrates the possibility to intercept
* method calls that are abou to be executed from the body of
* a certain method. This is achieved by using the {@linkplain Kind#CALL}
* location value.
*/
@OnMethod(clazz="javax.swing.JTextField", method="/.*/",
location=@Location(value=Kind.CALL, clazz="/.*/", method="/.*/"))
public static void m(Object self, String method) { // all calls to the methods with signature "()"
println(method);
println(probeMethod());
println(probeClass());
}
위의 스크립트는 javax.swing.JTextField 클래스를 호출하는(Kind.Call) 모든 Class(clazz="/.*/") 의 모든 method (method="/.*/") 들을 추적하여 TextField 메소드들 중에서 매개변수가 없는(즉 signature 가 () 인) 메소드를 호출한 호출자의 메소드 이름을 출력해 주는 예제입니다. 해당 스크립트를 Java2D(jdk demo\jfc 에 존재하는) 를 target 으로 실행하면 다음과 같은 결과를 보실 수 있습니다.
getInsets()Ljava/awt/Insets;
scrollRectToVisible
class javax.swing.JTextField
즉 JTextField의 scrollRectToVisible 메소드가 java.asw.Insets 의 getInsets 메소드에서 호출 되고 있음을 나타냅니다.
위의 OnMethod 에서 눈여겨 볼 부분은 @Location annotation 입니다. Location 의 종류는 여러가지가 있는데 몇가지만 소개 하면 다음과 같습니다.
Kind.Call : 해당 Class 의 해당 method 를 호출한 시점
Kind.Catch : method 의 exception 이 catch 되는 시점
Kind.Entry : method 가 호출 되기 바로 직전
Kind.Return : method 가 return 된 직후에
Kind.Line : method 의 해당 라인이 실행될때
Kind.Throw : method 가 exception 을 throw 할 때
각각의 Location 에 따라서 Action Method 에 Argument 들이 달라집니다. 예를 들어 Kind.Call 의 경우는
Object self, String method, Object arg1, Object arg2....
이런식으로 해당 probe point 를 호출하는 클래스 자체(self) 와 호출하는 메소드 이름(method), 그리고 메소드의 signature 즉 입력 매개변수들인 arg1, arg2 등을 매개변수로 받게 됩니다.(위의 m 메소드 참조)
Kind.Entry 및 Return 의 경우는
Object returned
즉 probe point 가 호출되고 나서 리턴되는 object(returned) 를 매개변수로 받게 됩니다. 즉 아래의 예를 보시기 바랍니다.
@OnMethod(
clazz="java.lang.ClassLoader",
method="defineClass",
location=@Location(Kind.RETURN)
)
public static void defineclass(Class cl) {
println(strcat("loaded ", name(cl)));
jstack();
println("==========================");
}
java.lang.ClassLoader.defineClass 의 return object 인 Class 타입을 매개변수로 받습니다.
BTrace 에 대한 간단한 소개는 이것으로 마치고 다음 글에는 action 메소드에서 유일하게 호출 가능한 com.sun.btrace.BTraceUtils 의 메소드들에 대해 설명 드리도록 하겠습니다.
첨부) action method 의 제약사항
1. 새로운 object 생성 불가
2. 새로운 array 생성 불가
3. exception throw 불가
4. exception catch 불가
5. 임시 instance 및 static method 호출 불가 -오직 com.sun.btrace.BTraceUtils 클래스의 static method 만 호출 가능
6. 타겟 프로그램의 클래스 혹은 오브젝트에 값의 설정 불가함. 그러나 BTrace class 자체의 state field 들에 대한 설정은 가능함.
7. public static void 타입의 method 만 BTrace 클래스의 메소드로 허락됨
8. inner, outer local 클래스의 사용 불가
8. 동기화 사용 불가(synchronized)
9. loop 사용 불가. 단 if 구문은 사용 가능함.
10. extend 불가능
11. 인터페이스 implement 불가
12. asset 구문 삽입 불가
13. Class literal 즉 this 의 사용 불가