繁体   English   中英

使用字节伙伴在Java级别进行测试

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM