标签: byte-buddy

使用Byte Buddy for Java Agent

我希望创建一个代理以附加到我们的实时Tomcat和Weblogic服务器,该代理将拦截对我的公司程序包中声明的所有类的所有方法调用,并记录一些指标,例如执行时间。

我遇到了Byte Buddy库,它似乎可以满足此需求。但是,对于使用Byte Buddy创建代理的方法,我还不是100%清楚:

我采用了创建自己的代理的方法,并使用Maven对其进行了打包,以将Byte Buddy作为胖子(这样Byte Buddy代码在类路径中)包括进了我的引用catalina.bat

编辑:自从我下载了源代码,并发现AgentBuilder依赖于byte-buddy-agent包,因此上述问题无关紧要。

Tomcat可以正常启动,并且可以看到代理被调用,就像看到的“ Entered premain”一样System.out

但是,System.out当我在部署到Tomcat的单独war文件上执行代码时,从未看到“已拦截” 。 编辑:以下代码根据拉斐尔的回应进行了更新,现在可以正常工作。

有人可以告诉我在这里我可能做错了什么吗?我已经在下面包含了代理代码。

另外,有人可以告诉我哪个ElementMatchers最适合软件包匹配吗?我尝试过,nameStartsWith但是没有任何效果,API文档也没有说明它是否是完全限定的类名。

*编辑:nameStartsWith会检查软件包。*

无论如何,在此先感谢您的帮助!

package com.mycompany.agent;

import java.lang.instrument.Instrumentation;
import java.util.concurrent.Callable;

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import net.bytebuddy.matcher.ElementMatchers;

public class MyAgent {

public static void premain(String agentArgument, Instrumentation instrumentation) {
    System.out.println("Entered premain");
    try{
        new AgentBuilder.Default()
                .withListener( new AgentBuilder.Listener() …
Run Code Online (Sandbox Code Playgroud)

java instrumentation bytecode byte-buddy

5
推荐指数
1
解决办法
1850
查看次数

在Android上使用Byte Buddy时出错

我正在尝试在Android中使用Byte Buddy库但我收到错误:

java.lang.IllegalStateException:此JVM的版本字符串似乎无效:0

我还没有编码,只是:

ByteBuddy test = new ByteBuddy();
Run Code Online (Sandbox Code Playgroud)

在我的App.java中

我已导入:

<dependency>
    <groupId>net.bytebuddy</groupId>
    <artifactId>byte-buddy</artifactId>
    <version>0.7.7</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

但它没有用,我尝试过:

<dependency>
    <groupId>net.bytebuddy</groupId>
    <artifactId>byte-buddy-android</artifactId>
    <version>0.7.7</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

但我仍然得到同样的错误.

编辑

在初始化ByteBuddy之前我已经把这行放了:

  System.setProperty("java.version", "1.7.0_51");
Run Code Online (Sandbox Code Playgroud)

但现在我又得到了另一个错误:

引起:java.lang.UnsupportedOperationException:无法加载此类类文件.

对于此代码:

Class<?> dynamicType = new ByteBuddy(ClassFileVersion.JAVA_V6)
            .subclass(Object.class)
            .method(ElementMatchers.named("toString"))
            .intercept(FixedValue.value("Hello World!"))
            .make()
            .load(getClass().getClassLoader(), AndroidClassLoadingStrategy.Default.WRAPPER)
            .getLoaded();
Run Code Online (Sandbox Code Playgroud)

java android byte-buddy

5
推荐指数
1
解决办法
944
查看次数

是否可以通过 ByteBuddy 的建议访问局部变量?

当使用 拦截方法的实现时@Advice,是否可以访问局部变量?

java java-bytecode-asm byte-buddy

5
推荐指数
1
解决办法
404
查看次数

Byte Buddy - 定义构造函数并调用超类和初始化字段

我有一个类,例如:

public class Sample{

private String a;
private String b;

public Sample(String a, String b)
{
    this.a = a;
    this.b = b;
}
 public String getA() {return a;}
 public String getB() {return b;}
}
Run Code Online (Sandbox Code Playgroud)

我想创建一个从 Sample 类继承的动态类,并向其中添加字段(字符串字段)。

我试图做:

DynamicType.Builder<? extends Sample> classBuilder = new ByteBuddy()
        .subclass(Sample.class, ConstructorStrategy.Default.NO_CONSTRUCTORS)
        .name("sampleSon");

classBuilder.defineConstructor(Visibility.PUBLIC)
        .withParameters(String.class, String.class, String.class)
        .intercept(MethodCall.invoke(Sample.class.getConstructor(String.class, String.class))
                .withArgument(0, 1)
                .andThen(FieldAccessor.ofField("c").setsArgumentAt(2)));
Run Code Online (Sandbox Code Playgroud)

但是当我尝试从这个类创建一个实例时:

Class<? extends Sample> newSampleClass= classBuilder.make().load(ClassLoader.getSystemClassLoader()).getLoaded();
Sample sample = newSampleClass.getConstructor(String.class, String.class, String.class).newInstance("a", "b", "c");
Run Code Online (Sandbox Code Playgroud)

它抛出一个异常:

public class Sample{

private String a;
private String …
Run Code Online (Sandbox Code Playgroud)

java dynamic-class dynamic-class-creation byte-buddy

5
推荐指数
1
解决办法
1754
查看次数

是否可以使用@Advice.OnMethodEnter 从方法返回?

使用 Byte Buddy 的建议 API,是否可以从检测方法返回而不实际执行它?

一种用例是实现缓存并返回缓存值(如果存在),而不是再次计算该值。

@Advice.OnMethodEnter
public static Object returnCachedValue(@Advice.Argument(0) String query) {
    if (cache.containsKey(query)) {
        // should "abort" method call
        return cache.get(query);
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道上面的这个代码示例只是创建了一个我可以在@Advice.OnMethodExit方法中获取的局部变量。但是有没有办法中止对显式的方法调用return?如果是,这也适用于void方法吗?

java byte-buddy

5
推荐指数
1
解决办法
1045
查看次数

构建会话工厂时,字节伙伴中的休眠 NoSuchMethodError

我整夜都在寻找,似乎在任何地方都找不到解决方案。每次我尝试从我的应用程序登录数据库时,我都会得到以下信息:

    java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774) ~[jfxrt.jar:?]
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657) ~[jfxrt.jar:?]
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) ~[jfxrt.jar:?]
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) ~[jfxrt.jar:?]
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) ~[jfxrt.jar:?]
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) ~[jfxrt.jar:?]
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) ~[jfxrt.jar:?]
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) ~[jfxrt.jar:?]
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) ~[jfxrt.jar:?]
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) ~[jfxrt.jar:?]
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) ~[jfxrt.jar:?]
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) ~[jfxrt.jar:?]
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) ~[jfxrt.jar:?]
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) ~[jfxrt.jar:?]
    at javafx.event.Event.fireEvent(Event.java:198) ~[jfxrt.jar:?]
    at javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3470) ~[jfxrt.jar:?]
    at javafx.scene.Scene$ClickGenerator.access$8100(Scene.java:3398) ~[jfxrt.jar:?]
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3766) ~[jfxrt.jar:?]
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485) ~[jfxrt.jar:?]
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762) ~[jfxrt.jar:?]
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494) ~[jfxrt.jar:?]
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:394) ~[jfxrt.jar:?]
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295) ~[jfxrt.jar:?]
    at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_181]
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$353(GlassViewEventHandler.java:432) ~[jfxrt.jar:?]
    at …
Run Code Online (Sandbox Code Playgroud)

java hibernate maven byte-buddy

5
推荐指数
1
解决办法
1504
查看次数

使用 Byte Buddy 在运行时添加方法注释

几天来,我一直在寻找“如何在运行时向方法添加注释”的答案,并找到了这个名为 Byte Buddy 的很棒的工具,使用了它,但仍然无法按我的需要工作。我确定它必须能够从这个问题Can Byte Buddy create fields and method annotations at runtime?

有这个类:

public class ClassThatNeedsToBeAnnotated {
  public void method(int arg1, String arg2) {
    // code that we don't want to touch at all, leave it as is
    System.out.println("Called method with arguments " + arg1 + " " + arg2);
  }

  public void method() {
    System.out.println("Called method without arguments");
  }
}
Run Code Online (Sandbox Code Playgroud)

和这个代码:

 public class MainClass {
      public static void main(String[] args) {
        ByteBuddyAgent.install();

        AnnotationDescription description = AnnotationDescription.Builder.ofType(MyClassAnnotation.class)
            .define("value", …
Run Code Online (Sandbox Code Playgroud)

java annotations byte-buddy

5
推荐指数
1
解决办法
639
查看次数

如何使用Byte Buddy创建具有每个枚举常量初始化的字段的枚举?

我想使用字节伙伴生成一个包含字段的枚举,其中每个枚举常量将不同的参数传递给构造函数。

public enum MyEnum {
    private final String blah;
    A("foo")
    B("bar");

    private MyEnum(String blah) {
        this.blah = blah;
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试了这个:

new ByteBuddy()
    .makeEnumeration("A", "B")
    .name("com.foo.MyEnum")
    .defineField("blah", String.class, Modifier.FINAL | Modifier.PRIVATE)
    .defineConstructor(Visibility.PRIVATE)
    .withParameters(String.class)
    .intercept(
        FieldAccessor.ofField("blah").setsArgumentAt(0)
    )
    .make()
Run Code Online (Sandbox Code Playgroud)

生成此文件(反编译)。具有相同签名的两个构造函数有些古怪,但无论如何。

public enum MyEnum {
    private final String blah;
    A,
    B;

    private MyEnum() {
    }

    private MyEnum() {
        this.blah = var1;
    }
}
Run Code Online (Sandbox Code Playgroud)

我看不到将每个枚举常量与一组构造函数参数关联的方法。该makeEnumeration方法只有两个签名,两个签名都使用字符串集合。

字节好友有可能吗?

java byte-buddy

5
推荐指数
0
解决办法
91
查看次数

在 Spring boot 应用程序中将mockito与mock-maker-inline一起使用时出现问题

我有一个 Spring Web 应用程序,可以在 \xe2\x80\x9cspecial\xe2\x80\x9d 模式下运行,其中使用 mockito 来监视某些对象。其中一些对象是最终的(protobuf 消息)。我知道,这可能听起来像是一个坏主意,但可以说它\xe2\x80\x99s 是一个实验。启用mock-maker-inline扩展时,可以在 I\xe2\x80\x99m 上监视最终对象,遇到似乎与字节伙伴和加载一些本机库相关的问题。当不使用扩展(并且不监视最终类)时,一切都会按预期工作。下面是截断的堆栈跟踪。

\n
java.lang.IllegalStateException: Could not initialize plugin: interface org.mockito.plugins.MockMaker (alternate: null)\n\xe2\x80\xa6\nCaused by: java.lang.IllegalStateException: Failed to load interface org.mockito.plugins.MockMaker implementation declared in sun.misc.CompoundEnumeration@60cc2b75\n\xe2\x80\xa6\nCaused by: java.lang.reflect.InvocationTargetException\n\xe2\x80\xa6\nCaused by: org.mockito.exceptions.base.MockitoInitializationException:\nCould not initialize inline Byte Buddy mock maker.\n\nIt appears as if your JDK does not supply a working agent attachment mechanism.\nJava               : 1.8\nJVM vendor name    : AdoptOpenJDK\nJVM vendor version : 25.265-b01\nJVM name           : OpenJDK 64-Bit Server VM\nJVM version        : 1.8.0_265-b01\nJVM info           : …
Run Code Online (Sandbox Code Playgroud)

mockito byte-buddy

5
推荐指数
1
解决办法
7767
查看次数

如何组合两个实现?

我有一个ImplementationAdvice#wrap(Implementation), 和 a的返回值产生的结果FixedValue。我需要把这些变成一个单一的Implementation不会导致字节码验证错误。

那是:

Implementation advisedMethodCall = Advice.to(...).wrap(someMethodCall);
Implementation firstArgument = FixedValue.argument(0);
// How can I "run" advisedMethodCall followed by firstArgument?
Run Code Online (Sandbox Code Playgroud)

更一般地说:我如何取两个Implementations(不是 的实例Implementation.Composable)并组合它们?

(我从之前的实验中知道,MethodCall通过某种名为 的内部类来实现这一点TerminationHandler,其中所讨论的特定实现TerminationHandler.Simple.DROPPING对堆栈执行某些操作以允许您组合MethodCalls。我不知道如何做与Implementationthat类似的事情不是MethodCall(例如,由 产生的Advice#wrap(Implementation))。)

java byte-buddy

5
推荐指数
1
解决办法
51
查看次数