![](/img/trans.png)
[英]get function arguments values using java asm for bytecode instrimentation
[英]Tracing method invocation arguments in bytecode using ASM
如何檢查類的字節碼(使用諸如ASM之類的東西)來了解哪些初始值傳遞給方法?
例如:給定一些將值互相傳遞的方法:
void m1(Object o) {
Object v = o;
m2(v);
m2("box");
}
void m2(Object o) {
Object v = o;
m3(x);
}
void m3(Object o) {
}
還有一些方法調用,都在同一個類中定義:
{
Object foo = "foo";
m1(foo);
m2("bar");
m3("baz");
}
我如何檢查類的字節碼,以了解m3
將被調用4次,值為"foo"
, "box"
, "bar"
和"baz"
?
使用ASM,理論上可以跟蹤每個方法,如果從其中調用同一個類的另一個方法。 訪問者API負責定義方法調用的方法是visitMethodIns
。 假設您的類名為bar.Foo
,您需要跟蹤:
visitMethodIns(<any>, "bar.Foo", <any>, <any>)
然后,您需要構建一個彼此調用的方法的傳遞關系,其中最后兩個參數允許您構建這樣的關系層次結構。 另外,您需要跟蹤這些方法調用的參數,更棘手但也不是不可能。
它更復雜的原因是參數可以加載到操作數堆棧的可能方式的數量。 對於您的示例,您只需要關注visitIns和visitLCDIns回調。
在常量池值(LCD)上調用方法時,參數的分辨率相當微不足道。 但是,在調用方法學習局部變量賦值之前,您需要跟蹤整個指令鏈,以便知道您正在調用方法參數上的方法。 因此,你可以找到答案
ALOAD_0 / ASTORE_1 / ALOAD_1 => ALOAD_0
從方法局部變量數組中讀取/寫入序列的有效結果。
有了這一切,通過解析字節代碼,您將了解以下調用轉換:
m1(Ljava/lang/Object)V -> m2(Ljava/lang/Object)V [ALOAD 0]
-> m2(Ljava/lang/Object)V [LCD "box"]
m2(Ljava/lang/Object)V -> m3(Ljava/lang/Object)V [ALOAD 0]
然后,您可以使用這些結果來解析塊,在那里您可以找到這些方法調用及其含義。 然而,你會創建一個非常脆弱的解決方案,其中的間接如下:
{
Foo foo = this;
foo.m1("bar");
}
不會被發現。 正如評論中所指出的,您基本上需要模擬Java虛擬機以“運行”您的代碼。
即使您實施了一個復雜的解決方案來追蹤所有這些,您仍然無法確定您的結果。 當我從實現中調用接口方法時會發生什么。 還是一個子類的方法? 由於動態調度方法,您永遠無法確定被調用的目標。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.