Operations 17 min read

BTrace: Introduction, Quick Start, and Detailed Usage Guide

This article introduces BTrace, a lightweight JVM tracing tool, explains its capabilities and limitations, provides step‑by‑step installation and configuration instructions, demonstrates example scripts for monitoring thread pools and other runtime information, and discusses usage scenarios, annotations, and related tools.

Qunar Tech Salon
Qunar Tech Salon
Qunar Tech Salon
BTrace: Introduction, Quick Start, and Detailed Usage Guide

Simple Introduction

BTrace is a JVM‑level tracing tool that can output information about a running Java process without affecting its execution. It works for any JVM language and is written as a Java script.

What BTrace can and cannot do

It can output real‑time JVM information such as object states, but it cannot perform operations that modify the JVM state.

Quick Start – Environment Setup

Required components:

btrace 1.3.8.3

beta environment

JDK 1.7.0_45

Tomcat 7

Installation steps:

mkdir btrace
cd btrace
wget http://github.com/btraceio/btrace/releases/download/v1.3.8.3-1/btrace-bin-1.3.8.3.tgz
tar -zxvf btrace-bin-1.3.8.3.tgz
sudo chown -R tomcat:tomcat btrace
export BTRACE_HOME=/xxx/btrace

After adding BTRACE_HOME to the environment, the script can be executed directly.

Example: Monitoring a ThreadPool

First, view the application PID (e.g., using jps or ps -ef | grep tomcat ). Then run BTrace with a sample script:

sudo -u tomcat ./btrace 2862 ../samples/ThreadStart.java

The console will display lines such as:

Thread starting InactivityMonitorAsyncTask: java.util.concurrent.ThreadPoolExecutor$Worker@333d7f6a[State=-1, empty queue]

If you encounter "Unable to open socket file: target process not responding or HotSpot VM not loaded", run the command with the same user as the target JVM (e.g., sudo -u user btrace … ).

BTrace Script Example (ThreadPoolBtrace.java)

/*
 * Copyright (c) 2012 Qunar.com. All Rights Reserved
 */
package com.btrace;
import com.sun.btrace.annotations.*;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;
import static com.sun.btrace.BTraceUtils.*;
@BTrace
public class ThreadPoolBtrace {
    @Property
    private static Map
executorMap = newHashMap();
    @Property
    private static AtomicInteger lock = newAtomicInteger(0);
    @OnMethod(clazz = "java.util.concurrent.ThreadPoolExecutor", method = "execute")
    public static void onExecuteRunnable(@Self ThreadPoolExecutor executor) {
        if (!containsKey(executorMap, executor) && compareAndSet(lock, 0, 1)) {
            println("==== begin ====");
            println(str(executor));
            Class clazz = classForName("java.util.concurrent.ThreadPoolExecutor");
            int corePoolSize = getInt(field(clazz, "corePoolSize", true), executor);
            println("corePoolSize size : " + corePoolSize);
            printQueueLength(executor);
            println("==== end ====");
            put(executorMap, executor, size(executorMap));
            compareAndSet(lock, 1, 0);
        }
    }
    private static void printQueueLength(ThreadPoolExecutor executor) {
        Class clazz = classForName("java.util.concurrent.ThreadPoolExecutor");
        BlockingQueue workQueue = (BlockingQueue) get(field(clazz, "workQueue", true), executor);
        if (workQueue != null) {
            if (matchClazz("java.util.concurrent.ArrayBlockingQueue", workQueue)) {
                clazz = classForName("java.util.concurrent.ArrayBlockingQueue");
                Object[] itemsInArray = (Object[]) get(field(clazz, "items", true), workQueue);
                println("workQueue size : " + itemsInArray.length);
            }
            if (matchClazz("java.util.concurrent.LinkedBlockingQueue", workQueue)) {
                clazz = classForName("java.util.concurrent.LinkedBlockingQueue");
                println("workQueue size : " + getInt(field(clazz, "capacity"), workQueue));
            }
        }
    }
    private static boolean matchClazz(String clazz, Object instance) {
        return compareTo("class " + clazz, str(classOf(instance))) == 0;
    }
    @OnTimer(5000)
    public static void timerLimit() {
        clear(executorMap);
    }
}

Compile and run the script with:

btrace -cp /xxx/jdk1.7.0_79/jre/lib/jfxrt.jar 21854 ../samples/ThreadPoolBtrace.java

BTrace Command Line Parameters

btrace [-I
] [-p
] [-cp
]
[
]

Key options: -I for include path, -p to set the agent port (default 2020), -cp for classpath, and script arguments accessible via $ and $length .

Important Notes & Limitations

BTrace must not modify JVM state; it can only read information.

Only BTraceUtils methods are allowed – no object creation, no throwing or catching exceptions, no loops, no synchronized blocks, etc.

All fields in a BTrace class must be static.

Script Annotations

Annotations such as @OnMethod , @OnTimer , @OnExit , @OnError , @OnEvent , and @OnLowMemory define when a tracing method is triggered. Parameter annotations like @Self , @ProbeClassName , @ProbeMethodName , @TargetInstance , @TargetMethodOrField , @Return , and @Duration provide context.

Technical Implementation

BTrace uses the Attach API to connect to a target JVM, the BTrace script engine together with ASM to transform bytecode, and JDK6 instrumentation to inject tracing code. The BTrace client compiles scripts, communicates with a BTrace agent via sockets, and the agent instruments loaded classes on‑the‑fly.

IDE Integration

In VisualVM, install the BTrace WorkBench plugin, then use Trace Application . Alternatively, add BTrace as a Maven dependency, write Java scripts in your IDE, and deploy them to the server.

Common Use Cases

Diagnosing live production issues without restarting the application.

Adding logging to third‑party JARs that cannot be modified.

Capturing stack traces for intermittent problems (e.g., unexpected Full GC).

Similar Tools

HouseMD – a Scala‑based interactive tracing tool (no longer maintained).

Greys – an Alibaba‑maintained interactive Java debugging tool.

Further Resources

Official BTrace documentation: BTrace Annotations

User guide: BTrace User Guide

Various blog posts and articles linked in the original source.

Instrumentationperformance monitoringBTraceJava debuggingJVM tracing
Qunar Tech Salon
Written by

Qunar Tech Salon

Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.