【问题标题】:Using ByteBuddy Java agent without -javaagent argument使用不带 -javaagent 参数的 ByteBuddy Java 代理
【发布时间】:2019-11-09 18:44:50
【问题描述】:

我正在尝试在项目中检测一些类。当我将代理类打包到一个 jar 中并通过 -javaagent 使用它时,它工作正常。

public static void premain(String arguments, Instrumentation instrumentation) {

        new AgentBuilder.Default()
                .type(ElementMatchers.nameStartsWith("com.cn."))
                .transform((builder, type, cl, m) -> builder
                        .method(ElementMatchers.isAnnotatedWith(Retryable.class))
                        .intercept(to(Retry.class)))
                .installOn(instrumentation);
    }

当我尝试直接在项目中运行它时,检测有时会失败。 (我在测试类的静态块中初始化 bytebuddy)。

    static {
        Instrumentation inst = ByteBuddyAgent.install();

        new AgentBuilder.Default()
                .type(ElementMatchers.nameStartsWith("com.cn."))
                .transform((builder, type, cl, m) -> builder
                        .method(ElementMatchers.isAnnotatedWith(Retryable.class))
                        .intercept(to(Retry.class)))
                .installOn(inst);
    }

例如,当我添加此测试时,我的代码不再被拦截。 对 try/catch 做同样的事情。

RuntimeException e = Assertions.assertThrows(RuntimeException.class, () -> f.doit("doit foo"));

是否有一种安全的方法可以在没有 -javaagent 的情况下检测同一项目中的类?

项目在 OpenJdk11 上。

【问题讨论】:

  • 您是否尝试向代理生成器添加侦听器以查看是否仍然发现了相关类型或是否存在错误?有没有检查block中的安装是否抛出异常?

标签: java byte-buddy


【解决方案1】:

使用 -javaagent 选项,您将始终确保在安装代理后加载您的类。

如果您将代理安装在静态块中,则必须确保在加载您要检测的任何类之前执行这段代码。例如。您可以将代理安装在您的主要方法中或主要方法所在的静态块中。

【讨论】:

  • 我检查了 Foo 类是否在测试类之后加载(静态块中的 system.out)。后来加载了。奇怪的是,“Assertions.assertThrows”的使用导致了这个问题...... Hibernate、Mockito 等所有的库是如何解决这个问题的?我从未使用带有 -javaagent 的应用程序,但它们都使用 Instrumentation。
  • Mockito 和 Hibernate 使用定义明确的生命周期,例如,如果使用内联模拟生成器显式重新转换任何模拟类型,则 Mockito 使用重新转换。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-22
  • 1970-01-01
相关资源
最近更新 更多