简体   繁体   English

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

[英]Instrument in java level using byte-buddy

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 我为仪器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);
}}

Can we Instrument java class like ThreadPoolExecutor using Byte Buddy. 我们可以使用Byte Buddy来插入ThreadPoolExecutor之类的Java类吗? When i debug ThreadPoolExecutor class working.But when i try this using agent ThreadPoolExecutor class never works. 当我调试ThreadPoolExecutor类的工作时。但是,当我尝试使用代理ThreadPoolExecutor类进行此操作时,它将永远无法工作。

Edit This is my MonitorInterceptor 编辑这是我的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);

Unless you configure it explicitly, Byte Buddy does not instrument core Java classes. 除非明确配置,否则Byte Buddy不会检测核心Java类。 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. 在这种情况下,使用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. 为了找出问题所在,您还可以定义一个AgentBuilder.Listener来通知错误。

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类。

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. 我使用javassist来获取构造函数,并按照字节伙伴给出的那样获取它。 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 因此,使用.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