[英]Is MethodDelegation intercept with ByteBuddy possible on Android?
[英]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.