Instrument in java level using byte-buddy

℡╲_俬逩灬. 提交于 2020-01-06 05:10:14

问题


I have a code for Thread Pool example as follows

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();
}}

and

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();
    }
}}

The i create a small agent for instrument java ThreadPoolExecutor as follows

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);
}}

Can we Instrument java class like ThreadPoolExecutor using Byte Buddy. When i debug ThreadPoolExecutor class working.But when i try this using agent ThreadPoolExecutor class never works.

Edit This is my MonitorInterceptor

public class MonitorInterceptor {


@Advice.OnMethodEnter
static void enter(@Advice.Origin String method) throws Exception {

    System.out.println(method);

}

Edit

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);

回答1:


Unless you configure it explicitly, Byte Buddy does not instrument core Java classes. You can change that by explicitly setting an ignore matcher that does not exclude such classes.

In this context, it should not be necessary to configure an initialization strategy when using Advice.

You might also want to limit the scope of your advice, right now you intercept any method or constructor.

For finding out what is wrong, you can also define an AgentBuilder.Listener to be notified of errors.




回答2:


Using Rafael Winterhalter answer i get solved this problem. I create an agent as follows ,

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); 

Using this we can instrument Java class.Form this constructor giving like this

java.util.concurrent.ThreadPoolExecutor$Worker(java.util.concurrent.ThreadPoolExecutor,java.lang.Runnable)

But in code constructor not like that, its is

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

So I expect something like

java.util.concurrent.ThreadPoolExecutor(int,int,long,java.util.concurrent.TimeUnit,java.util.concurrent.BlockingQueue)

I used javassist to get constructor and get its as what byte-buddy gives. So using .ignore(ElementMatchers.none()) and visit(Advice.to(ThreadPoolExecutorAdvice.class).on(ElementMatchers.any()))we can get all constructors and methods in Java level class



来源:https://stackoverflow.com/questions/49321938/instrument-in-java-level-using-byte-buddy

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!