DTrace-style oneliners for quick Java debugging without writing full scripts.
BTrace oneliners provide a fast, concise way to debug running Java applications without creating separate script files. Inspired by DTrace oneliners, they compile to standard BTrace Java code internally, ensuring zero performance overhead.
When to use oneliners:
- Quick debugging in production
- Ad-hoc performance investigation
- Learning BTrace basics
- Prototyping before writing full scripts
When to use full BTrace scripts:
- Complex logic with multiple probe points
- State management across probes
- Custom data structures
- Reusable instrumentation
# Basic syntax
btrace -n 'class::method @location { action }' <PID>
# Real examples
btrace -n 'javax.swing.*::setText @entry { print method, args }' 1234
btrace -n 'java.sql.Statement::execute* @return if duration>100ms { print method, duration }' 1234
btrace -n 'java.util.HashMap::get @entry { count }' 1234class-pattern::method-pattern @location [filter] { action [, action]* }
Components:
class-pattern- Class name with wildcards or regexmethod-pattern- Method name with wildcards or regex@location- Where to probe:@entry,@return, or@errorfilter(optional) - Conditional filteraction- What to do:print,count,time, orstack
Wildcards (simple pattern matching):
# Match all classes in package
'javax.swing.*::*'
# Match all subpackages
'javax.swing.**::*'
# Match method names
'MyClass::get*'
'MyClass::*Service'Regex (advanced pattern matching):
# Regex in class name
'/com\.myapp\..*/::execute'
# Regex in method name
'java.sql.Statement::/execute.*/'
# Both
'/com\.myapp\..*/::/handle.*/Special method names:
<init>- Constructors<clinit>- Static initializers*- All methods
| Location | Description | Available Identifiers |
|---|---|---|
@entry |
Method entry | method, args, self, class |
@return |
Method return | method, args, duration, return, self, class |
@error |
Exception thrown | method, args, duration, self, class |
Examples:
# Trace method entry
btrace -n 'MyClass::myMethod @entry { print method }' <PID>
# Trace method return
btrace -n 'MyClass::myMethod @return { print method, return }' <PID>
# Trace exceptions
btrace -n 'MyClass::myMethod @error { print method, stack }' <PID>Duration filter (only for @return and @error):
# Slow methods > 100ms
'MyClass::* @return if duration>100ms { print method, duration }'
# Very slow methods >= 500ms
'MyClass::* @return if duration>=500ms { print method }'
# Fast methods < 10ms
'MyClass::* @return if duration<10ms { print method }'Argument filter (all locations):
# String argument equals
'MyClass::process @entry if args[0]=="CREATE" { print }'
# Numeric argument comparison
'MyClass::setValue @entry if args[0]>100 { print args }'
# Check null
'MyClass::process @entry if args[1]==null { print method }'Supported comparators:
>- Greater than<- Less than==- Equals>=- Greater than or equal<=- Less than or equal!=- Not equals
# Print bare message
{ print }
# Print specific identifiers
{ print method }
{ print method, args }
{ print method, duration, return }
# Available identifiers:
# method - Method name
# args - Method arguments
# duration - Execution time (nanoseconds, @return/@error only)
# return - Return value (@return only)
# self - This instance
# class - Class nameExamples:
# Method with arguments
btrace -n 'MyClass::process @entry { print method, args }' <PID>
# Slow method with timing
btrace -n 'MyClass::query @return if duration>100ms { print method, duration }' <PID>
# Return value
btrace -n 'MyClass::calculate @return { print method, return }' <PID># Simple count
{ count }Prints total count when BTrace exits (Ctrl+C).
Examples:
# Count HashMap.get calls
btrace -n 'java.util.HashMap::get @entry { count }' <PID>
# Count exceptions
btrace -n 'java.lang.Exception::<init> @entry { count }' <PID># Display execution time in milliseconds
{ time }Only valid for @return and @error locations.
Examples:
# Time database queries
btrace -n 'java.sql.Statement::execute* @return { time }' <PID>
# Time method execution
btrace -n 'MyClass::expensiveOperation @return { time }' <PID># Full stack trace
{ stack }
# Limited depth
{ stack(10) }Examples:
# Stack on OutOfMemoryError
btrace -n 'java.lang.OutOfMemoryError::<init> @return { stack(10) }' <PID>
# Call path to method
btrace -n 'MyClass::suspiciousMethod @entry { stack(5) }' <PID>Separate actions with commas:
# Print and count
{ print method, count }
# Print, count, and stack
{ print method, count, stack(3) }Find slow database queries:
btrace -n 'java.sql.Statement::execute* @return if duration>100ms { print method, duration }' <PID>Find slow HTTP requests:
btrace -n 'javax.servlet.http.HttpServlet::service @return if duration>500ms { print method, duration }' <PID>Time all methods in a class:
btrace -n 'com.myapp.MyService::* @return { time }' <PID>Trace all Swing UI updates:
btrace -n 'javax.swing.*::* @entry { print method, args }' <PID>Monitor file operations:
btrace -n 'java.io.FileInputStream::<init> @entry { print args }' <PID>Count cache hits:
btrace -n 'com.myapp.Cache::get @entry { count }' <PID>Track all exceptions:
btrace -n 'java.lang.Exception::<init> @entry { print self, stack(5) }' <PID>Track specific exception:
btrace -n 'java.sql.SQLException::<init> @entry { print self, stack(10) }' <PID>Monitor OutOfMemoryError:
btrace -n 'java.lang.OutOfMemoryError::<init> @return { stack(15) }' <PID>Track user objects:
btrace -n 'com.myapp.User::<init> @entry { print args, count }' <PID>Monitor configuration changes:
btrace -n 'com.myapp.Config::set* @entry { print method, args }' <PID>Track specific argument values:
btrace -n 'com.myapp.OrderService::process @entry if args[0]=="PRIORITY" { print method, args, stack }' <PID>Find who's calling deprecated methods:
btrace -n 'com.myapp.LegacyService::oldMethod @entry { print stack(3) }' <PID>Identify slow REST endpoints:
btrace -n 'org.springframework.web.bind.annotation.RequestMapping::* @return if duration>1000ms { print method, duration }' <PID>Monitor database connection usage:
btrace -n 'javax.sql.DataSource::getConnection @entry { count }' <PID>Match multiple packages:
btrace -n '/com\.myapp\.(service|controller)\..*/::* @entry { print method }' <PID>Match getter/setter methods:
btrace -n 'com.myapp.User::/[gs]et.*/ @entry { print method, args }' <PID>Slow methods with stack traces:
btrace -n 'com.myapp.*::* @return if duration>200ms { print method, duration, stack(5) }' <PID>Count specific argument values:
btrace -n 'com.myapp.OrderService::processOrder @entry if args[0]=="EXPRESS" { count }' <PID>Filter by return value (manual workaround - not directly supported yet):
# Use duration filter as proxy for successful operations
btrace -n 'com.myapp.Service::operation @return if duration>0ms { print return }' <PID>Current limitations of Alternative 1 (Minimal) oneliners:
- Single probe point - Cannot have multiple probes in one oneliner
- No aggregations - Cannot use histograms, averages, etc.
- No CALL location - Cannot intercept method calls within methods
- No field access - Cannot track field reads/writes
- Simple filters only - No AND/OR logic in filters
- No state - Cannot maintain variables across invocations
Future enhancements (Alternative 2):
- Multi-probe support:
probe1 | probe2 | probe3 - Aggregations:
@hist=histogram; ... { @hist << duration by method } - CALL location:
@call:TargetClass::targetMethod - Grouping:
by method, class
-
Use specific patterns instead of wildcards when possible:
# Good - specific 'com.myapp.UserService::getUserById' # Less optimal - very broad '**::*'
-
Add filters to reduce overhead:
# Only trace slow calls @return if duration>100ms
-
Limit stack depth:
# Good { stack(5) } # Expensive { stack } # full stack
-
Start broad, then narrow:
# Step 1: Find which class btrace -n 'com.myapp.*::* @entry { print class, method }' <PID> # Step 2: Focus on specific class btrace -n 'com.myapp.UserService::* @entry { print method, args }' <PID> # Step 3: Drill into specific method btrace -n 'com.myapp.UserService::getUserById @entry { print args, stack }' <PID>
-
Use count to quantify issues:
# How often is this called? btrace -n 'com.myapp.Database::query @entry { count }' <PID>
-
Combine with external tools:
# Save output to file btrace -n 'com.myapp.*::* @entry { print method }' <PID> > trace.log # Pipe to grep btrace -n 'com.myapp.*::* @entry { print method }' <PID> | grep "User"
-
Oneliners run in untrusted mode by default - Use
-uflag for trusted operations -
Be careful with production - Test oneliners in staging first
-
Use read-only actions -
print,count,stackare safe; avoid modifying state
Problem: Oneliner runs but produces no output
Solutions:
-
Verify the method is being called:
# Add entry point btrace -n 'MyClass::* @entry { print method }' <PID>
-
Check pattern matching:
# Try exact match first btrace -n 'com.example.MyClass::myMethod @entry { print }' <PID>
-
Verify location:
# Try all locations btrace -n 'MyClass::myMethod @entry { print }' <PID> btrace -n 'MyClass::myMethod @return { print }' <PID>
Problem: "Oneliner syntax error at position X"
Solutions:
-
Check quotes - use single quotes for shell:
# Correct btrace -n 'MyClass::method @entry { print }' <PID> # Wrong - shell interprets $ btrace -n "MyClass::method @entry { print }" <PID>
-
Check spacing around symbols:
# Correct if duration>100ms # Wrong ifduration>100ms
-
Verify filter location:
# Error - duration only for @return/@error '@entry if duration>100ms' # Correct '@return if duration>100ms'
Problem: "Oneliner compilation failed"
Solutions:
-
Enable debug mode to see generated code:
btrace -v -n 'MyClass::method @entry { print }' <PID>
-
Check for unsupported features:
- Duration filter requires
@returnor@error - Return identifier requires
@return
- Duration filter requires
-
Try equivalent full BTrace script to isolate issue
When you outgrow oneliners, convert them to full BTrace scripts:
Oneliner:
btrace -n 'MyClass::process @return if duration>100ms { print method, duration }' <PID>Equivalent BTrace script (MyTrace.java):
import org.openjdk.btrace.core.annotations.*;
import static org.openjdk.btrace.core.BTraceUtils.*;
@BTrace
public class MyTrace {
@OnMethod(clazz="MyClass", method="process", location=@Location(Kind.RETURN))
public static void onProcess(@ProbeMethodName String method, @Duration long duration) {
if (duration > 100_000_000L) { // 100ms in nanoseconds
println(method + " " + duration);
}
}
}- Getting Started Guide - Installation and basics
- BTrace Tutorial - Comprehensive BTrace features
- Quick Reference - Full annotation reference
- FAQ - Common questions
- Troubleshooting Guide - Problem solving
Found an issue or have a suggestion for oneliners? Please:
- Report on GitHub Issues
- Tag with
onelinerlabel - Include example oneliner and expected behavior