首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否可以使用ByteBuddy拦截数组构造函数?

是否可以使用ByteBuddy拦截数组构造函数?
EN

Stack Overflow用户
提问于 2020-07-11 06:17:10
回答 3查看 135关注 0票数 1

我有一个回归测试,在这里我试图计算数组的实例化数。具体来说,我对计算new int[..]被调用多少次感兴趣。我已经整理了以下基于ByteBuddy建议的工具,我认为它应该捕获所有的构造函数,但是这并不适用于数组(任何类型的):

代码语言:javascript
运行
复制
public class InstanceCounter {
  public static void load() {
    ClassInjector.UsingUnsafe.ofBootLoader().injectRaw(Collections.singletonMap("foo.bar.BootstrapState", readBytes(InstanceCounter.class.getClassLoader().getResource("foo/bar/BootstrapState.class"))));
    new AgentBuilder.Default()
      .ignore(none())
      .disableClassFormatChanges()
      .with(RedefinitionStrategy.RETRANSFORMATION)
      .with(InitializationStrategy.NoOp.INSTANCE)
      .with(TypeStrategy.Default.REDEFINE)
    .type(any())
      .transform(new Transformer() {
        @Override
        public Builder<?> transform(final Builder<?> builder, final TypeDescription typeDescription, final ClassLoader classLoader, final JavaModule module) {
          return builder.visit(Advice.to(InstanceCounter.class).on(any()));
        }})
    .installOn(ByteBuddyAgent.install());
  }

  @Advice.OnMethodEnter
  public static void enter(final @Advice.Origin Class<?> origin) {
    if (!BootstrapState.trace || BootstrapState.lock)
      return;

    BootstrapState.lock = true;
    System.out.println(">>> " + origin);
    BootstrapState.lock = false;
  }
}

public class InstanceCounterTest {
  @Test
  public void test() {
    InstanceCounter.load();
    System.out.println("Creating array...");
    BootstrapState.trace = true;
    final Object[] y = new Object[3];
    BootstrapState.trace = false;
    System.out.println("Printing array: " + y);
  }
}

当我运行这个测试时,我得到以下结果:

代码语言:javascript
运行
复制
Creating array...
Printing array: [Ljava.lang.Object;@7f5eae0f

如果我将final Object[] y = new Object[3]更改为new Object(),则输出如下:

代码语言:javascript
运行
复制
Creating array...
>>> class java.lang.Object
Printing array: [Ljava.lang.Object;@68562ad5

我已经使建议工具尽可能开放(至少我认为我可以打开它),但这仍然没有对数组对象的构造进行检测。

甚至可以测量数组对象的构造吗?

更新2020-07-28

根据最初问题的上下文,所提供的答案表明,ByteBuddy不直接支持new int[]的自动检测。然而,对于那些对另一种解决方案感兴趣的人,我能够用拜特曼实现这种工具。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-07-12 21:43:18

如前所述,不能更改数组类,因为它们不是在类文件中表示的。相反,您需要拦截它们的创建,这需要进行一些字节代码解析。

Buddy公开了ASM,它使用它自己来完成这种工作,但它比拦截构造函数更多的是手工工作。

票数 1
EN

Stack Overflow用户

发布于 2020-07-11 06:42:37

数组没有构造函数;它们是用newarray (对于原语)或anewarray (对于引用类型)创建的(如果您想要获得创造性,也可以使用multianewarray )。

如果您想要修改数组创建,您必须找到某种方法来检测这些字节码指令。

票数 1
EN

Stack Overflow用户

发布于 2020-07-11 06:43:58

常规对象构造的工具包括向相关类的构造函数中注入一个调用。这是可行的,因为每个类至少声明一个构造函数,并且在对象创建过程中总是调用构造函数。

相反,数组没有构造函数,因此没有地方注入调用。这就解释了为什么您的所有构造函数的工具都没有选择数组创建。

假设情况下,另一种创建仪器数组的方法是找到使用3个"newarray“字节码的所有位置,并在它们之前使用一个检测调用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62845863

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档