mirror of
https://github.com/alibaba/arthas.git
synced 2024-04-21 10:21:39 +00:00
add ByteKitDemo
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
package com.example;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.ClassNode;
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode;
|
||||
import com.taobao.arthas.bytekit.asm.MethodProcessor;
|
||||
import com.taobao.arthas.bytekit.asm.binding.Binding;
|
||||
import com.taobao.arthas.bytekit.asm.interceptor.InterceptorProcessor;
|
||||
import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtEnter;
|
||||
import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtExceptionExit;
|
||||
import com.taobao.arthas.bytekit.asm.interceptor.annotation.AtExit;
|
||||
import com.taobao.arthas.bytekit.asm.interceptor.annotation.ExceptionHandler;
|
||||
import com.taobao.arthas.bytekit.asm.interceptor.parser.DefaultInterceptorClassParser;
|
||||
import com.taobao.arthas.bytekit.utils.AgentUtils;
|
||||
import com.taobao.arthas.bytekit.utils.AsmUtils;
|
||||
import com.taobao.arthas.bytekit.utils.Decompiler;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengyunabc 2020-05-21
|
||||
*
|
||||
*/
|
||||
public class ByteKitDemo {
|
||||
|
||||
public static class Sample {
|
||||
private int exceptionCount = 0;
|
||||
|
||||
public String hello(String str, boolean exception) {
|
||||
if (exception) {
|
||||
exceptionCount++;
|
||||
throw new RuntimeException("test exception, str: " + str);
|
||||
}
|
||||
return "hello " + str;
|
||||
}
|
||||
}
|
||||
|
||||
public static class PrintExceptionSuppressHandler {
|
||||
|
||||
@ExceptionHandler(inline = true)
|
||||
public static void onSuppress(@Binding.Throwable Throwable e, @Binding.Class Object clazz) {
|
||||
System.out.println("exception handler: " + clazz);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static class EnterInterceptor {
|
||||
|
||||
@AtEnter(inline = true, suppress = RuntimeException.class, suppressHandler = PrintExceptionSuppressHandler.class)
|
||||
public static void atEnter(@Binding.This Object object,
|
||||
@Binding.Class Object clazz,
|
||||
@Binding.Args Object[] args,
|
||||
@Binding.MethodName String methodName,
|
||||
@Binding.MethodDesc String methodDesc) {
|
||||
System.out.println("atEnter, args[0]: " + args[0]);
|
||||
}
|
||||
|
||||
@AtExit(inline = true)
|
||||
public static void atExit(@Binding.Return Object returnObject) {
|
||||
System.out.println("atExit, returnObject: " + returnObject);
|
||||
}
|
||||
|
||||
@AtExceptionExit(inline = true, onException = RuntimeException.class)
|
||||
public static void atExceptionExit(@Binding.Throwable RuntimeException ex,
|
||||
@Binding.Field(name = "exceptionCount") int exceptionCount) {
|
||||
System.out.println("atExceptionExit, ex: " + ex.getMessage() + ", field exceptionCount: " + exceptionCount);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
AgentUtils.install();
|
||||
|
||||
// 启动Sample,不断执行
|
||||
final Sample sample = new Sample();
|
||||
Thread t = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(3);
|
||||
String result = sample.hello("" + i, (i % 3) == 0);
|
||||
System.out.println("call hello result: " + result);
|
||||
} catch (Throwable e) {
|
||||
// ignore
|
||||
System.out.println("call hello exception: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
|
||||
// 解析定义的 Interceptor类 和相关的注解
|
||||
DefaultInterceptorClassParser interceptorClassParser = new DefaultInterceptorClassParser();
|
||||
List<InterceptorProcessor> processors = interceptorClassParser.parse(EnterInterceptor.class);
|
||||
|
||||
// 加载字节码
|
||||
ClassNode classNode = AsmUtils.loadClass(Sample.class);
|
||||
|
||||
// 对加载到的字节码做增强处理
|
||||
for (MethodNode methodNode : classNode.methods) {
|
||||
if (methodNode.name.equals("hello")) {
|
||||
MethodProcessor methodProcessor = new MethodProcessor(classNode, methodNode);
|
||||
for (InterceptorProcessor interceptor : processors) {
|
||||
interceptor.process(methodProcessor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取增强后的字节码
|
||||
byte[] bytes = AsmUtils.toBytes(classNode);
|
||||
|
||||
// 查看反编译结果
|
||||
System.out.println(Decompiler.decompile(bytes));
|
||||
|
||||
// 等待,查看未增强里的输出结果
|
||||
TimeUnit.SECONDS.sleep(10);
|
||||
|
||||
// 通过 reTransform 增强类
|
||||
AgentUtils.reTransform(Sample.class, bytes);
|
||||
System.in.read();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user