簡體   English   中英

是否可以使用 ByteBuddy 攔截數組構造函數?

[英]Is it possible to intercept array constructor with ByteBuddy?

我有一個回歸測試,我試圖計算 arrays 的實例化數量。 具體來說,我有興趣計算調用new int[..]的次數。 我已經整理了以下基於 ByteBuddy 建議的工具,我認為它應該捕獲所有構造函數,但這不適用於 arrays(任何類型):

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);
  }
}

當我運行這個測試時,我得到以下結果:

Creating array...
Printing array: [Ljava.lang.Object;@7f5eae0f

如果我將final Object[] y = new Object[3]更改為new Object() ,那么 output 是:

Creating array...
>>> class java.lang.Object
Printing array: [Ljava.lang.Object;@68562ad5

我已經使建議工具盡可能開放(至少在我認為可以做到的范圍內開放),但這仍然沒有檢測數組對象的構造。

甚至可以檢測數組對象的構造嗎?

2020-07-28 更新

根據原始問題的上下文,提供的答案表示 ByteBuddy 不直接支持自動檢測new int[] 但是,對於那些對替代解決方案感興趣的人,我能夠使用Byteman實現這種檢測。

Arrays 沒有構造函數; 它們是使用newarray (用於基元)或anewarray (用於引用類型)創建的(如果您想獲得創意,還有multianewarray )。

如果要修改數組創建,則必須找到某種方法來檢測這些字節碼指令。

常規對象構造的檢測涉及將調用注入到相關 class 的構造函數中。 這是可行的,因為每個 class 至少聲明一個構造函數,並且因為在 object 創建期間始終調用構造函數。

相比之下,arrays 沒有構造函數,因此無法注入調用。 這就解釋了為什么您對所有構造函數的檢測都沒有拾取數組創建。

假設,儀器數組創建的另一種方法是找到使用 3 個“newarray”字節碼的所有位置,並在它們之前進行檢測調用。

正如所指出的,您不能更改數組類,因為它們沒有在 class 文件中表示。 相反,您需要攔截它們的創建,這需要一些字節碼解析。

Byte Buddy公開了 ASM,它使用它自己來完成這種工作,但它比攔截構造函數要手動得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM