BTrace的 wiki:

例子

测试代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package com.test;

public class OrderProcessor {
    public void processOrder(int quantity, double unitPrice) {
        double discount = 0.1;
        double totalPrice = (quantity * unitPrice) - (quantity * unitPrice * discount);
        System.out.println("Total price after discount: " + totalPrice);
    }

    public static void main(String[] args) throws InterruptedException {
        OrderProcessor processor = new OrderProcessor();
        while (true) {
            processor.processOrder(5, 20.0);  // Simulate order processing
            Thread.sleep(5000); // Simulate delay between processing
        }
    }
}

btrace程序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import org.openjdk.btrace.core.annotations.*;
import static org.openjdk.btrace.core.BTraceUtils.*;

@BTrace
public class TraceLocalVariables {

	@OnMethod(
		clazz = "com.test.OrderProcessor",
		method = "processOrder"
	)
	public static void traceVariables(int quantity, double unitPrice) {
		println("Method processOrder is called with parameters:");
		println("quantity: " + quantity);
		println("unitPrice: " + unitPrice);
		jstack();
	}
}

启动 btrace

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
btrace.bat 92712 .\TraceLocalVariables.java

[main] INFO org.openjdk.btrace.client.Main - Attaching BTrace to PID: 92712
[main] INFO org.openjdk.btrace.client.Client - Successfully started BTrace probe: .\TraceLocalVariables.java
Method processOrder is called with parameters:

quantity: 5

unitPrice: 20.0

com.test.OrderProcessor.processOrder(OrderProcessor.java)
com.test.OrderProcessor.main(OrderProcessor.java:13)

也可以用 arthas 实现 将 OrderProcessor 内容改一下:

1
2
3
4
5
6
    public void processOrder(int quantity, double unitPrice) {
        double discount = 0.1;
        double totalPrice = (quantity * unitPrice) - (quantity * unitPrice * discount);
        //System.out.println("Total price after discount: " + totalPrice);
		System.out.println("haha -> " + discount + "," + totalPrice);
    }

重新编译一下,然后 arthas retransform 加载:

1
2
3
4
5
6
retransform /data/test/OrderProcessor.class

retransform -l
Id              ClassName       TransformCount  LoaderHash      LoaderClassName
3               com.test.OrderP 1               null            null
                rocessor

可以用 jad 反编译检查一下
再看原先的程序,打印的内容变了

1
2
3
4
Total price after discount: 90.0
Total price after discount: 90.0
haha -> 0.1,90.0
haha -> 0.1,90.0

官网的一些例子:

Feature BTrace Arthas retransform
Purpose Monitoring and tracing at runtime Modifying class behavior at runtime
Instrumentation Non-intrusive (read-only) tracing Intrusive (modifies class bytecode)
Ease of Use Script-based, specific tracing logic Requires you to provide modified bytecode
Scope Limited to tracing (no class modification) Allows full modification of class/methods
Runtime Overhead Minimal Can be higher, depending on modification

对比一下

  • arthas 使用了:Instrumentation.retransformClasses(),会替换整个类,风险高
  • btrace 使用了:java.lang.instrument,只是在关键函数中注入了额外信息,风险低

jdb 的一个例子
编译的时候需要加 -g

1
2
3
javac -d . -g .\OrderProcessor.java

java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -cp . com.test.OrderProcessor

使用 jdb 跟踪

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
jdb -connect com.sun.jdi.SocketAttach:hostname=[your ip],port=5005
设置未捕获的java.lang.Throwable
设置延迟的未捕获的java.lang.Throwable
正在初始化jdb...
> threads
组system:
  (java.lang.ref.Reference$ReferenceHandler)0x1b5 Reference Handler正在执行条件等待
  (java.lang.ref.Finalizer$FinalizerThread)0x1b6  Finalizer        正在执行条件等待
  (java.lang.Thread)0x1b7                         Signal Dispatcher正在运行
  (java.lang.Thread)0x1b8                         Attach Listener  正在运行
组main:
  (java.lang.Thread)0x1                           main             正在休眠

进入之后,输入 help,会列出所有调试命令
打断点做调试

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
> stop at com.test.OrderProcessor:8
设置断点com.test.OrderProcessor:8
>
断点命中: "线程=main", com.test.OrderProcessor.processOrder(), =8 bci=19

main[1] locals
方法参数:
quantity = 5
unitPrice = 20.0
本地变量:
discount = 0.1
totalPrice = 90.0
main[1]

其他一些分析工具

分布式监控

  • Prometheus
  • Grafana
  • ELK Stack
  • Zipkin
  • Jaeger

Arthas

  • monitor、watch、trace 等很好用的工具
  • 还有 jad、dashborad、getstatic、ognl
  • profiler 记录火焰图
  • jfr,jfr 记录

JDK 内置工具

  • jstack、jinfo、jps、jmap
  • jstat、jconsole、jcmd、jhat
  • jdb
  • Mission Control

监控工具

内存 dump分析

  • Elicpse MAT
  • NetBeans Profiler

APM 工具

  • New Relic
  • AppDynamics
  • Datadog APM

其他

  • strace
  • Perf (Linux) + async-profiler

参考