[英]Instrument in java level using byte-buddy
我有一個線程池示例的代碼,如下所示
public class RunThreads{
static final int MAX_TASK = 3;
public static void main(String[] args)
{
Runnable r1 = new Task("task 1");
Runnable r2 = new Task("task 2");
Runnable r3 = new Task("task 3");
Runnable r4 = new Task("task 4");
Runnable r5 = new Task("task 5");
ExecutorService pool = Executors.newFixedThreadPool(MAX_TASK);
pool.execute(r1);
pool.execute(r2);
pool.execute(r3);
pool.execute(r4);
pool.execute(r5);
pool.shutdown();
}}
和
class Task implements Runnable{
private String name;
public Task(String s)
{
name = s;
}
public void run()
{
try
{
for (int i = 0; i<=5; i++)
{
if (i==0)
{
Date d = new Date();
SimpleDateFormat ft = new SimpleDateFormat("hh:mm:ss");
System.out.println("Initialization Time for"
+ " task name - "+ name +" = " +ft.format(d));
//prints the initialization time for every task
}
else
{
Date d = new Date();
SimpleDateFormat ft = new SimpleDateFormat("hh:mm:ss");
System.out.println("Executing Time for task name - "+
name +" = " +ft.format(d));
// prints the execution time for every task
}
Thread.sleep(1000);
}
System.out.println(name+" complete");
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}}
我為儀器java ThreadPoolExecutor
創建一個小型代理,如下所示
public class Agent {
public static void premain(String arguments, Instrumentation instrumentation) {
new AgentBuilder.Default()
.with(new AgentBuilder.InitializationStrategy.SelfInjection.Eager())
.type((ElementMatchers.nameContains("ThreadPoolExecutor")))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.include(MonitorInterceptor.class.getClassLoader())
.advice(ElementMatchers.any(), MonitorInterceptor.class.getName())
).installOn(instrumentation);
}}
我們可以使用Byte Buddy來插入ThreadPoolExecutor之類的Java類嗎? 當我調試ThreadPoolExecutor類的工作時。但是,當我嘗試使用代理ThreadPoolExecutor類進行此操作時,它將永遠無法工作。
編輯這是我的MonitorInterceptor
public class MonitorInterceptor {
@Advice.OnMethodEnter
static void enter(@Advice.Origin String method) throws Exception {
System.out.println(method);
}
編輯
new AgentBuilder.Default()
.with(new AgentBuilder.InitializationStrategy.SelfInjection.Eager())
.with(AgentBuilder.Listener.StreamWriting.toSystemError())
.ignore(none())
.type((ElementMatchers.nameContains("ThreadPoolExecutor")))
.transform((builder, typeDescription, classLoader, module) -> builder
.constructor(ElementMatchers.any())
.intercept(Advice.to(MyAdvice.class))
.method(ElementMatchers.any())
.intercept(Advice.to(MonitorInterceptor.class))
).installOn(instrumentation);
除非明確配置,否則Byte Buddy不會檢測核心Java類。 您可以通過顯式設置不排除此類的忽略匹配器來更改此設置。
在這種情況下,使用Advice時不必配置初始化策略。
您可能還想限制建議的范圍,現在您攔截任何方法或構造函數。
為了找出問題所在,您還可以定義一個AgentBuilder.Listener來通知錯誤。
使用拉斐爾·溫特豪德答案我解決了這個問題。 我如下創建一個代理,
new AgentBuilder.Default()
.ignore(ElementMatchers.none())
.type(ElementMatchers.nameContains("ThreadPoolExecutor"))
.transform((builder, type, classLoader, module) -> builder
.visit(Advice.to(ThreadPoolExecutorAdvice.class).on(ElementMatchers.any()))
).installOn(instrumentation);
使用這個我們可以檢測Java類。
java.util.concurrent.ThreadPoolExecutor$Worker(java.util.concurrent.ThreadPoolExecutor,java.lang.Runnable)
但是在代碼構造器中並不是這樣,它是
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
所以我期望像
java.util.concurrent.ThreadPoolExecutor(int,int,long,java.util.concurrent.TimeUnit,java.util.concurrent.BlockingQueue)
我使用javassist來獲取構造函數,並按照字節伙伴給出的那樣獲取它。 因此,使用.ignore(ElementMatchers.none())
和visit(Advice.to(ThreadPoolExecutorAdvice.class).on(ElementMatchers.any()))
可以獲取Java級別類中的所有構造函數和方法
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.