2

Я пытаюсь манипулировать статическим методом. Для этого можно использовать Byte Buddy или любую другую структуру.Изменение поведения статического метода при манипулировании Java-байтом

Существует одна библиотека, которая называется Pi4J, которая используется для управления GPIO из малины Pi. Эта библиотека имеет метод:

GpioController gpio = GpioFactory.getInstance(); 

И этот вызов называется в нескольких местах программы, которую я не мог контролировать такое, что мне нужно изменить вызов.

Что я хотел бы сделать, так это то, что когда GpioFactory.getInstance каким-то образом обнаруживает и модифицирует методы GpioController, чтобы они регистрировались, что они были вызваны.

Возможно, единственным решением является использование AspectJ, но знаете ли вы, может ли Byte Buddy быть решением?

ответ

2

Код для Pi4J с открытым исходным кодом на github по лицензии LGPL. Вы можете просто клонировать репозиторий, изменять его и использовать собственную версию. Если вы чувствуете, что ваши изменения могут помочь другим, подумайте о том, чтобы внести вклад в tp pi4j.

+0

Ну, что я хочу сделать, это что-то конкретное для Аркиллиана. – lordofthejars

+1

thats fine - все еще, изменив «вашу копию» pi4j, вы с меньшей вероятностью потерпите крах, если изменения версии pi4j – Jan

1

Это возможно при использовании Java agent в сочетании с Byte Buddy. Например, вы можете изменить GpioFactory::getInstance метод, с помощью следующего Java агента:

public class MyAgent { 
    public static void premain(String arg, Instrumentation inst) { 
    new AgentBuilder.Default() 
     .type(ElementMatchers.named("com.pi4j.io.gpio.GpioFactory") 
     .transform((builder, type) -> // Or anonymous class for pre Java 8 
      builder.method(ElementMatchers.named("getInstance")) 
       .intercept(MethodDelegation.to(MyFactory.class)); 
    ).installOn(inst) 
    } 
} 

public class MyFactory { 
    public static GpioController intercept(@SuperCall Callable<GpioController> s) 
     throws Exception { 
    return s.call(); // Wrap controller here. 
    } 
} 

Используя этот агент, Любой экземпляр контроллера, который возвращается из исходного getInstance метода будет передаваться с помощью метода MyFactory::intercept.

В качестве альтернативы вы можете в равной мере задействовать все реализации GpioController, чтобы непосредственно вести журнал. Это повлияет на все экземпляры интерфейса.

Если вы не имеете возможность добавить агент Java при запуске, на JDKs (не стандартные JVMs), вы можете использовать ByteBuddyAgent.install() (от byte-buddy-agent зависимости), чтобы вручную установить агент во время выполнения. В этом случае вам необходимо убедиться, что агент установлен до загружен GpioFactory. Дополнительную информацию вы можете найти на странице documentation of the library.

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

Смежные вопросы