Преобразование классов с помощью Byte Buddy

Может ли Byte Buddy Instrumentation#retransformClasses уже загрузиться? Я хочу использовать функцию Java-агента Byte Buddy, чтобы мне не нужно было указывать -javaagent, чтобы иметь возможность инструментировать классы. Это возможно, например, с Javassist. Но я подумываю заменить его на Byte Buddy.

Я хочу вставить вызов статического метода до и после определенных методов. Если это возможно, короткий пример был бы замечательным!


person Felix    schedule 13.03.2016    source источник


Ответы (1)


Да, вы можете использовать AgentBuilder API для повторного преобразования. После установки агента Byte Buddy повторно преобразует все уже загруженные классы. Вы можете включить повторное преобразование следующим образом:

AgentBuilder builder = new AgentBuilder.Default()    
  .with(RedefinitionStrategy.RETRANSFORMATION)
  .with(InitializationStrategy.NoOp.INSTANCE)
  .with(TypeStrategy.Default.REDEFINE);

Вы можете задаться вопросом о различных переключателях, которые вам нужно повернуть:

  1. Вам необходимо включить переопределение (либо переопределение, либо повторное преобразование в соответствии с инструментальным API).

  2. Вам необходимо отключить явную стратегию инициализации. В противном случае Byte Buddy пытается добавить явный инициализатор в любой сгенерированный класс, чтобы внедрить любые значения в класс после его загрузки. Это изменит макет класса, который не поддерживает текущая реализация виртуальной машины HotSpot.

  3. Как уже упоминалось, одно ограничение инструментального API заключается в том, что вы не можете добавлять какие-либо новые методы. По умолчанию Byte Buddy копирует код любого перехваченного метода в новый метод, что нарушает этот принцип. Включив стратегию переопределения типа, вы гарантируете, что Byte Buddy никогда не перебазирует метод.

Кроме того, вы можете не использовать API-интерфейс перехвата Byte Buddy, который теперь полностью заменяет перехватываемые методы, а выполнять переопределение вручную, используя, например, недавно добавленный класс Advice.

Таким образом, вы можете улучшить существующий код, посоветовав своему собственному коду, такому как Advice.to(Foo.class), где байт-код ссылочного класса вставляется до и после перехватываемого метода:

class Foo {
  @Advice.OnMethodEnter
  @Advice.OnMethodExit
  private static void intercept() {
    System.out.println("Before/after");
  }
}

Дополнительную информацию можно найти в javadoc для Advice.

person Rafael Winterhalter    schedule 14.03.2016