Инструмент на уровне Java с использованием 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);
}}

Можем ли мы инструментировать класс Java, например ThreadPoolExecutor, с помощью Byte Buddy. Когда я отлаживаю класс 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);
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
652
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если вы не сконфигурируете его явно, Byte Buddy не будет использовать базовые классы Java. Вы можете изменить это, явно установив сопоставление игнорирования, которое не исключает такие классы.

В этом контексте нет необходимости настраивать стратегию инициализации при использовании Advice.

Вы также можете ограничить объем своего совета, прямо сейчас вы перехватываете любой метод или конструктор.

Для определения того, что не так, вы также можете определить AgentBuilder.Listener, который будет получать уведомления об ошибках.

Я добавил слушателя, как показано ниже, .with(AgentBuilder.Listener.StreamWriting.toSystemError()), и я получил этот [Byte Buddy] DISCOVERY java.util.concurrent.ThreadPoolExecutor$Worker [null, null, loaded=false] [Byte Buddy] IGNORE java.util.concurrent.ThreadPoolExecutor$Worker [null, null, loaded=false] [Byte Buddy] COMPLETE java.util.concurrent.ThreadPoolExecutor$Worker [null, null, loaded=false] . Это нормально . Поэтому я думаю, что это игнорирование класса java

Shehan aklanka perera 17.03.2018 14:54

Вы пробовали игнорировать (none ()) в построителе?

Rafael Winterhalter 17.03.2018 15:14

`.ignore (ElementMatchers.none ())` Я использовал это и надеюсь, что моя проблема теперь решена.

Shehan aklanka perera 17.03.2018 15:20

У меня есть еще одна проблема: в нем не отображается конструктор ThreadPoolExecutor, нужно ли мне для этого добавить .constructor(ElementMatchers.any())?

Shehan aklanka perera 20.03.2018 06:53

Зависит от того, как сейчас выглядит ваш прибор

Rafael Winterhalter 20.03.2018 07:41

Я все еще использую вышеуказанный агент и добавил свой MonitorInterceptor

Shehan aklanka perera 20.03.2018 09:37

Эта проблема конструктора возникает только при попытке инструментария ThreadPoolExecutor. Я пробую это для обычного класса, и он отлично работает для конструктора и методов.

Shehan aklanka perera 20.03.2018 11:48

Нет сообщений об ошибках, и когда я добавляю .constructor(ElementMatchers.any()), часть метода также не работает

Shehan aklanka perera 20.03.2018 12:21

Я добавил свой модифицированный агент, если я заменю ThreadPoolExecutor на нормальный класс, он работает правильно.

Shehan aklanka perera 20.03.2018 12:24

Вероятно, вы захотите расширить класс с помощью .visit(Advice.to(MyAdvice.class).on(any()).

Rafael Winterhalter 20.03.2018 19:36

Мне также нужно настроить класс java.lang.Thread, но он также не показывает ни одного слушателя. но при отладке это происходит

Shehan aklanka perera 21.03.2018 05:51

Позвольте нам продолжить обсуждение в чате.

Shehan aklanka perera 21.03.2018 07:26

Используя ответ Рафаэля Винтерхальтера, я решил эту проблему. Я создаю агента следующим образом,

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.

Другие вопросы по теме