Safe, dynamic tracing for Java applications
BTrace dynamically instruments running Java applications to inject tracing code at runtime. No restarts. No recompilation. Production-safe.
Quick links: Quick Reference · Step-by-Step Tutorial
- Zero downtime - Attach to running JVMs without restart
- Production safe - Verified scripts can't crash your application
- Flexible probes - Method entry/exit, timings, field access, allocations
- Low overhead - Bytecode injection with minimal performance impact
# Install via JBang (easiest)
curl -Ls https://sh.jbang.dev | bash -s - app setup
# Add the BTrace JBang catalog (one time)
jbang catalog add --name btraceio https://raw.githubusercontent.com/btraceio/jbang-catalog/main/jbang-catalog.json
# Trace slow methods in your running app
jbang btrace@btraceio -n 'com.myapp.*::* @return if duration>100ms { print method, duration }' $(pgrep -f myapp)Method timing:
btrace -n 'java.sql.Statement::execute* @return { print method, duration }' <PID>Exception tracking:
btrace -n 'java.lang.Exception::<init> @return { print self, stack(5) }' <PID>Custom probes:
@BTrace public class Trace {
@OnMethod(clazz = "com.example.OrderService", method = "checkout")
public static void onCheckout(@Self Object self, @Duration long ns) {
println(strcat("checkout: ", str(ns/1_000_000) + "ms"));
}
}See the Oneliner Guide for complete syntax.
# JBang (recommended - zero installation)
jbang catalog add --name btraceio https://raw.githubusercontent.com/btraceio/jbang-catalog/main/jbang-catalog.json
jbang btrace@btraceio <PID> script.java
# SDKMan
sdk install btrace
# Manual download
curl -LO https://github.com/btraceio/btrace/releases/latest/download/btrace-bin.tar.gzSee Installation Guide for Docker, package managers, and more options.
| Resource | Description |
|---|---|
| Quick Reference | Cheat sheet for experienced users |
| Getting Started | Step-by-step first trace tutorial |
| Full Tutorial | Complete walkthrough of all features |
| Oneliners | DTrace-style quick probes |
| Extensions | StatsD, custom integrations |
| Documentation Hub | All docs and guides |
git clone https://github.com/btraceio/btrace.git
cd btrace
./gradlew :btrace-dist:buildSee CLAUDE.md for development setup and architecture.
Get help: Slack · Gitter · GitHub Issues
Contribute: Pull requests require signing the Oracle Contributor Agreement.
Tips:
- Prefer IPv4 if your environment has odd local IPs: set
GRADLE_OPTS="-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=false". - Run specific modules:
- Runtime:
./gradlew :btrace-runtime:test - Extension:
./gradlew :btrace-extension:test - Compiler:
./gradlew :btrace-compiler:test - Instr:
./gradlew :btrace-instr:test
- Runtime:
- Update instrumentor golden files when bytecode output changes:
./gradlew test -PupdateTestData.
Integration tests (optional):
./gradlew --no-daemon integration-tests:testThese may exercise privileged extensions. If you run into permission denials, provide a policy file and pass it to the test JVMs via -Dbtrace.permissions=/path/to/permissions.properties.
Use JBang to run BTrace without manual installation:
# Install JBang (one time)
curl -Ls https://sh.jbang.dev | bash -s - app setup
# Use BTrace immediately (replace <version> with desired version, e.g., 2.3.0)
jbang org.openjdk.btrace:btrace-client:<version> <PID> <script.java>
# After first run, use shorter alias
jbang btrace <PID> <script.java>Note: Replace <version> with the desired BTrace version (e.g., 2.3.0). See releases for available versions.
Benefits: Zero installation, automatic version management, works everywhere (Windows/macOS/Linux/containers), perfect for CI/CD.
Extract agent JARs (if needed for --agent-jar/--boot-jar flags):
# Extract embedded JARs
jbang btrace --extract-agent ~/.btrace
# This creates ~/.btrace/btrace.jar (single masked JAR)
# Then use them:
jbang btrace --agent-jar ~/.btrace/btrace.jar <PID> <script.java>
# Or find in Maven local repository (after first jbang run):
# ~/.m2/repository/org/openjdk/btrace/btrace/<version>/btrace-<version>.jar
#
# Legacy jar names (btrace-agent.jar, btrace-boot.jar) are still extracted for backward compatibility.See Getting Started Guide for complete JBang documentation and examples.
Download: Get the latest release from the release page
# Extract the archive
tar -xzf btrace-*.tar.gz
# or
unzip btrace-*.zip
# Set environment variables (optional but recommended)
export BTRACE_HOME=/path/to/btrace
export PATH=$BTRACE_HOME/bin:$PATH# RPM-based systems
sudo rpm -i btrace-*.rpm
# Debian-based systems
sudo dpkg -i btrace-*.debDocker images:
# Copy BTrace into your application image
FROM btrace/btrace:latest AS btrace
FROM bellsoft/liberica-openjdk-debian:11-cds
COPY --from=btrace /opt/btrace /opt/btrace
ENV BTRACE_HOME=/opt/btrace PATH="${PATH}:${BTRACE_HOME}/bin"
# Your application...Available variants:
btrace/btrace:latest- Debian-based (~25MB)btrace/btrace:latest-alpine- Alpine-based (~15MB)btrace/btrace:latest-distroless- Distroless (~10MB)
See docker/README.md for complete Docker documentation.
With JBang (no installation required):
# Attach to running application
jbang btrace <PID> <trace_script.java>
# Extract agent JARs
jbang btrace --extract-agent ~/.btraceWith installed BTrace:
# Attach to running application
btrace <PID> <trace_script.java>
# Compile BTrace script
btracec <trace_script.java>
# Launch application with BTrace agent
btracer <compiled_script.class> <java-application-and-args>Extensions add functionality via a stable API on bootstrap and an isolated implementation. See the extension development guide and examples.
Note: The legacy libs/profiles mechanism is deprecated and planned for removal after N+2 minor releases. Prefer packaging integrations as extensions and using provided-style class loading patterns (object hand-off + TCCL). For migration guidance and examples, see:
docs/architecture/migrating-from-libs-profiles.mddocs/architecture/provided-style-extensions.mddocs/examples/README.md
As a last resort (discouraged), you may append a single jar to the system classpath: -Dbtrace.system.appendJar=/abs/path/lib.jar -Dbtrace.trusted=true.
For environments where managing multiple JARs is impractical (Spark, Hadoop, Kubernetes), BTrace provides a fat agent JAR with embedded extensions:
# Build fat agent with all extensions
./gradlew :btrace-dist:fatAgentJar
# Build with specific extensions only
./gradlew :btrace-dist:fatAgentJar -PembedExtensions=btrace-metrics,btrace-statsd
# Use the fat agent
java -javaagent:btrace-agent-fat.jar <your-app>The fat agent JAR includes:
- All agent and boot classes
- Embedded extension API classes (bootstrap)
- Embedded extension impl classes (runtime-loaded)
- Extension metadata for auto-discovery
For custom fat agent builds, use the Gradle plugin:
plugins {
id 'org.openjdk.btrace.fat-agent'
}
btraceFatAgent {
embedExtensions {
maven('io.btrace:btrace-metrics:2.3.0')
project(':my-custom-extension')
}
}See Fat Agent Plugin Architecture and Gradle Plugin README for details.
BTrace now supports DTrace-style oneliners for quick debugging without writing full Java scripts:
# Trace method entry with arguments
btrace -n 'javax.swing.*::setText @entry { print method, args }' <PID>
# Find slow database queries (>100ms)
btrace -n 'java.sql.Statement::execute* @return if duration>100ms { print method, duration }' <PID>
# Count method invocations
btrace -n 'java.util.HashMap::get @entry { count }' <PID>
# Print stack trace on OutOfMemoryError
btrace -n 'java.lang.OutOfMemoryError::<init> @return { stack(10) }' <PID>Supported features:
- Locations:
@entry,@return,@error - Actions:
print,count,time,stack - Filters:
if duration>NUMBERms,if args[N]==VALUE - Patterns: Wildcards (
*,?) and regex (/pattern/)
See Oneliner Guide for complete syntax and examples.
For comprehensive documentation, tutorials, and guides:
- BTrace Documentation Hub - Complete documentation index with learning paths, quick reference, troubleshooting, and more
- Getting Started Guide - Get up and running in 5 minutes
- BTrace Wiki - External wiki with additional resources
BTrace supports extensions (like StatsdExtension) that provide additional functionality. Extensions require explicit permissions for security:
- Default permissions (always granted): MESSAGING, AGGREGATION, JFR_EVENTS, PROFILING
- Standard permissions (granted unless denied): FILE_READ, SYSTEM_PROPS, THREAD_INFO, MEMORY_INFO
- Privileged permissions (require explicit grant): FILE_WRITE, NETWORK, THREADS, NATIVE, EXEC, REFLECTION, CLASSLOADER, UNLIMITED_MEMORY
Permissions are enforced based on extension/service descriptors and agent grants specified at attach-time.
Grant permissions at runtime:
btrace --grant=NETWORK,THREADS <PID> MyProbe.classIf extensions fail to load, use -le to troubleshoot:
btrace -le <PID>See the Tutorial for detailed documentation.
Extensions CLI: use btracex to inspect and manage extensions and the simplified permission policy:
btracex inspect <zip|dir>prints extension id, version, services, and whether it’s privileged.btracex policy print|set [--policy-file <path>|--home|--classpath <outDir>]editsallowExtensions,denyExtensions,allowPrivileged.btracex listshows installed extensions;btracex installinstalls from Maven coordinates.
Note: Extension “required permissions” are informational and help operators assess risk. Implementation linking is controlled by per‑extension allow/deny lists and the allowPrivileged flag; when blocked, APIs remain available and SHIMs are used so probes continue safely.
- Launch-time policy can be set via agent args (operator-controlled):
-javaagent:btrace.jar=...,grant=NETWORK,THREADS,grantAll=false-javaagent:btrace.jar=...,allowExtensions=btrace-statsd,my-metrics,denyExtensions=legacy-foo
- Optional policy file (process-local):
-Dbtrace.permissions=/path/to/permissions.propertiesor~/.btrace/permissions.properties. - When an extension impl is blocked, the API remains on bootstrap so SHIMs can be generated.
See docs/PermissionPolicy.md for details and examples.
- Launch:
btracex inspect(with no args) opens an interactive view of installed extensions. - Header: shows current policy file path and the list of scanned repositories.
- Table: columns State, Id, Version. State uses compact symbols:
?(default),+(allowed),-(denied). - Details: selection updates automatically; shows the full-word state:
default/allowed/deniedand the full path. - Legend: a short legend under the table maps the state symbols.
Screenshot / demo (optional):
See also: docs/TUI.md for recording tips and an ASCII preview.
Keys
- Navigate: Arrow keys, PageUp/PageDown, Home/End
- Toggle state: space (flows
? → + (confirm) → - → +; onlycclears to default) - Clear:
c(removes extension id from both allow and deny lists) - Explain privileges:
e(opens a dialog with required permissions and risk descriptions) - Filter:
/(filter by id or path) - Sort:
s(choose column; repeat to toggle asc/desc) - Adjust split:
m(enter mode), then Up/Down to resize; pressEscormagain to exit - Help / Quit:
?/q
Fat Agent Plugin (in this repo): Build fat agent JARs with embedded extensions:
<plugin>
<groupId>org.openjdk.btrace</groupId>
<artifactId>btrace-maven-plugin</artifactId>
<version>${btrace.version}</version>
<configuration>
<extensions>
<extension>io.btrace:btrace-metrics:${btrace.version}</extension>
</extensions>
</configuration>
</plugin>Script Compilation Plugin (external repo):
- Compilation of BTrace scripts during the build process
- BTrace Project Archetype for quick project setup
Important: Pull requests can only be accepted from signers of the Oracle Contributor Agreement.
See CLAUDE.md for detailed development guidelines and project architecture.
- Slack: btrace.slack.com
- Gitter: gitter.im/btraceio/btrace
- Issues: GitHub Issues
GPLv2 with Classpath Exception. See LICENSE.
Credits: Built with ASM, JCTools, hppcrt. Optimized with JProfiler.

