的对 System.gc()
的调用。静态分析能探测的许多 bug 模式(包括这个模式)也能被方面探测
到;
根据具体的 bug 模式,用静态分析或用方面来做可能会更容易,所以把它们都放在工
具库中,可以提高效果。
清 单 1
显 示 了 一 个 简 单 的 动 态 方 面 , 在 要 调 用 System.gc() 时 , 抛 出
AssertionError。(
因为这类 bug 探测器的一个重要作用是不仅要找到您自己代码中的错误 ,
还要找到代码依赖的库中的错误,所以可能需要告诉工具还要分析或处理这些库。)
清单 1.
“
执行 不调用 System.gc()” 规则的动态方面
1 public aspect GcAspect {
2 pointcut gcCalls() : call(void java.lang.System.gc());
3
4 before() : gcCalls() {
5 throw new AssertionError("Don't call System.gc!");
6 }
7 }
8
清单 1 演示的动态方式不如使用静态分析进行测试有效,因为它要求程序在方
面发现问题之前,实际地执行对 System.gc() 的调用,而不是程序只需包含一个对
System.gc() 的调用,就会被探测到。但是,很快就会看到,动态方面更灵活,因为它们能
在方面触发的点上执行任意测试代码,从而对声明的问题提供更精细的控制。
也可以容易地创建一个静态方面,在编译时识别对 System.gc() 的调用,如清单
2
所示。同样,如果想发现在库代码中出现的这个 bug 模式,不仅要处理项目中的代码,
还要处理它使用的库。
清单 2.
“
执行 不调用 System.gc()” 规则的静态方面
1 public aspect StaticGcAspect {
2 pointcut gcCalls() : call(void java.lang.System.gc());
3
4 declare error : gcCalls() : "Don't call System.gc!";
5 }
6
检查对 Swing 单线程规则的违犯
——
有一个几乎无法静态地实施的规则是线程限制
指定的对象只能从一个线程
访问(
有时是特定线程,例如 Swing 事件线程)。Swing 程序的正确性依赖于线程限制,但
是对于实施这个规则,从编译器、运行时或类库都得不到任何帮助。如果违犯了这个规则,
程序就会被破坏,但是因为在测试时程序可能看起来工作正常,所以问题可能一直暴露
不了。