Byteman问题:Location Specifiers对List/Map的API操作无效
Byteman监听List/Map操作的规则触发异常问题
我尝试用Byteman的Location Specifier监听List/Map的操作,发现一个问题:调用List/Map的API(比如add方法)添加元素时,对应的规则完全没触发;但用赋值运算符=给list变量赋值时,规则能正常触发。我原本预期每次执行list.add这类操作后规则都会触发,但实际没发生,看起来Location逻辑只识别赋值运算符=的操作。
以下是测试代码、Byteman规则及输出截图:
测试代码
import java.util.*; public class SimpleTest { public static void main(String[] args) { System.out.println("Java: Entering main"); for (int i = 1; i <= 1; i++) { loopTest(i); try { Thread.sleep(1000); } catch(InterruptedException e) { System.out.println(e); } } } public static void loopTest(int i) { System.out.println("Java: Iteration " + i); Integer a; a=new Integer(1); a=new Integer(2); a=new Integer(3); System.out.println("Java: a is " + a); System.out.println(" *********************** "); //创建List List<String> list=new ArrayList<String>(); //向List添加元素 list.add("Mango"); list.add("Apple"); list.add("Banana"); //用for-each循环遍历List for(String fruit:list) { System.out.println("Java: list is" + fruit); } //重新初始化list list=Arrays.asList("foo", "bar"); //用for-each循环遍历新的List for(String fruit:list) { System.out.println("Java: list (new) is" + fruit); } } }
Byteman规则
RULE trace main entry CLASS SimpleTest METHOD main AT ENTRY IF true DO System.out.println("Byteman detected you are entering main - test") ENDRULE RULE catch_SimpleTest.loopTest CLASS SimpleTest METHOD loopTest COMPILE AT ENTRY IF true DO System.out.println("Byteman Enter loopTest - " + $1) ENDRULE RULE catch_SimpleTest.loopTest0 CLASS SimpleTest METHOD loopTest COMPILE AFTER WRITE $a 0 IF true DO System.out.println("Byteman loopTest0: " + $a) ENDRULE RULE catch_SimpleTest.loopTest1 CLASS SimpleTest METHOD loopTest COMPILE AFTER WRITE $a 1 IF true DO System.out.println("Byteman loopTest1: " + $a) ENDRULE RULE catch_SimpleTest.loopTest2 CLASS SimpleTest METHOD loopTest COMPILE AFTER WRITE $a 2 IF true DO System.out.println("Byteman loopTest2: " + $a) ENDRULE RULE catch_SimpleTest.loopTest3 CLASS SimpleTest METHOD loopTest COMPILE AFTER WRITE $a 3 IF true DO System.out.println("Byteman loopTest3: " + $a) ENDRULE RULE catch_SimpleTest.loopTestALL CLASS SimpleTest METHOD loopTest COMPILE AFTER WRITE $a ALL IF true DO System.out.println("Byteman loopTestALL: " + $a) ENDRULE RULE catch_SimpleTest.loopTestList1 CLASS SimpleTest METHOD loopTest COMPILE AFTER WRITE $list 1 IF true DO System.out.println("Byteman loopTestList1: " + $list) ENDRULE RULE catch_SimpleTest.loopTestList2 CLASS SimpleTest METHOD loopTest COMPILE AFTER WRITE $list 2 IF true DO System.out.println("Byteman loopTestList2: " + $list) ENDRULE RULE catch_SimpleTest.loopTestList3 CLASS SimpleTest METHOD loopTest COMPILE AFTER WRITE $list 3 IF true DO System.out.println("Byteman loopTestList3: " + $list) ENDRULE
Byteman输出截图

问题解决方法
你的规则只监听了变量赋值操作(AFTER WRITE $list),这类Location Specifier仅针对list变量本身的赋值(比如list = new ArrayList()或list = Arrays.asList(...)),而list.add()是调用List对象的方法,修改的是对象内部的状态,并没有改变list变量的引用值,所以不会触发你定义的AFTER WRITE $list规则。
要监听add这类List操作,你需要把规则的目标类改成List的实现类(比如ArrayList),并监听对应的方法:
示例规则1:监听ArrayList的add方法
RULE trace ArrayList add operation CLASS java.util.ArrayList METHOD add AT ENTRY IF true DO System.out.println("Byteman detected ArrayList.add called with element: " + $1) ENDRULE
示例规则2:监听所有List实现类的add方法
RULE trace List add operation CLASS java.util.List METHOD add AT ENTRY IF true DO System.out.println("Byteman detected List.add called with element: " + $1) ENDRULE
关键说明
AFTER WRITE $var这类Location是监听局部变量/字段的赋值行为,只有当变量的引用被改变时才会触发;- 要监听对象的方法调用,需要将规则的
CLASS指定为方法所在的类(或接口),METHOD指定为目标方法名,用AT ENTRY或AT EXIT来定位方法执行的时机。
修改后,每次调用list.add()时,对应的Byteman规则就会触发。
内容的提问来源于stack exchange,提问作者Asif Ansari
相关产品推荐
相关产品推荐

