I tried Btrace (
http://btrace.dev.java.net/) it is a debugging tool for Java. I have often been in the situation that a bug has been found in a production system. The production system must run even as I try to find the cause of the bug. That means the (java) program cannot be restarted to add some remote debugging ports or some other start-up options. This is where Btrace comes in. With Btrace you can write small script-like java code fragments so the program can be traced. Btrace accomplishes this by dynamically instrumenting the code.
Let’s take an example. Let’s say your production system tries to find numbers in the Fibonacci sequence:
import java.util.ArrayList;
import java.util.List;
public class FibonacciService {
private List<Integer> list = new ArrayList<Integer>();
public FibonacciService() {
//First two numbers in Fibonacci sequence.
list.add(0);
list.add(1);
new Thread(new Runnable() {
public void run() {
while (true) {
calculateNext();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "calc-thread").start();
}
private void calculateNext() {
int oldOld = list.get(list.size() - 2);
int old = list.get(list.size() - 1);
int newNumber = nextFibonacci(oldOld, old);
list.add(newNumber);
System.out.println(newNumber);
}
private static int nextFibonacci(int oldOld, int old) {
return oldOld + old;
}
public static void main(String args[]) {
new FibonacciService();
}
}
This Btrace code fragment will print out a trace string to the Btrace console every time the method calculateNext is entered:
@OnMethod(
clazz="se.lesc.btrace_example1.FibonacciService",
method="calculateNext"
)
public static void onStartCalc() {
println("Starting to calculate new number...");
}
Btrace code fragments can be attached to running java processes in two ways. Either use the command line “btrace” command or use a plugin to Suns Java VisualVM. Java VisualVM is like a Jconsole on steroids. It s is included in the JDK bundle since 1.6 update 7 (or something like that). You will find it in the JDK installation directory (either in tools, or in bin). Follow these instructions to add Btrace capabilities to VisualVM:
http://btrace.dev.java.net/visualvm_uc.html.
When installed, right click on the process and select “Trace application…”.

Then paste (or write) the code fragment and press Start. When pressing Start it takes a few seconds for the code to be instrumented. The output is shown in the console below the code fragment.

A little bit more advanced fragment that will print the method arguments when the method nextFibonacci is called:
@OnMethod(
clazz="se.lesc.btrace_example1.FibonacciService",
method="nextFibonacci"
)
public static void onNextFibonacci(int oldOld, int old) {
print("Input values are ");
print(str(oldOld));
print(" and " );
print(str(old));
println();
}
A fragment that prints out the return value when the nextFibonacci method is returned:
@OnMethod(
clazz="se.lesc.btrace_example1.FibonacciService",
method="nextFibonacci",
location=@Location(Kind.RETURN)
)
public static void onNextFibonacci(int returnValue) {
print("Result is: ");
print(str(returnValue));
println();
}
There are some restrictions on how advanced the fragments can be. Because the code must never get stuck loops are not allowed. Creating objects arbitrary is not allowed nor calling any methods (except from the BTraceUtils class).
Everything is not good about Btrace:
- Slow web page. Perhaps not Btrace fault. The entire *.dev.java.net servers are so slow that it is annoying.
- There is always a risk when instrumenting the code. Out of about 30 runs I had 3 unexpected crashes of the JVM that I can remember. It is with other words somewhat of a risk to run Btrace in a production environment.
- Some features don’t work. For example I tried to use a regular expression to match a method but every time I got java.lang.VerifyError (Edit: I've now submitted a bug report for it: https://btrace.dev.java.net/issues/show_bug.cgi?id=41). Another example is that I tried to get a reference to the current object in side a method, but it did not work.
- The documentation is need improvment. For example Btrace uses some kind of signature matching to find methods with arguments. How this matching is done is not documented. Such a central feature is really important to have documented.
- The project does not look to be actively developed. The last implemented ticket was submitted the 22th of February in 2009. Even critical and easy to fix problems is not fixed. For example in my opinion the bug about that Btrace cannot be run on Windows when there exist a space in the path should really be fixed. Edit: the project apparently has active development, based on the comments on this blog entry. :)