Java 理论与实践: 平衡测试,第 2 部分:编写和优化 bug 检测器
2010-01-11 00:00:00 来源:WEB开发网汇总结果
在获得所需的关于捕获和抛出异常的信息后,最后一步是汇总这些信息。在超类 visit(Code) 的调用返回后,将完全填充 throwList 和 caughtList 集合。它们包含关于方法中所有 try-catch 块的信息,所以您必须将抛出信息和捕获信息关联,以标识 bug 模式。
清单 6 显示了用于标识 RuntimeException 捕获的逻辑。它将迭代捕获块的列表,如果发现捕获 Exception 的块,它会再次查找捕获块,该捕获块将捕获字节码同一范围的 RuntimeException。它还可以查找在字节码的相应范围中抛出 Exception 的实例。如果没有捕获 RuntimeException,也没有抛出 Exception,则存在一个潜在的 bug。
清单 6. 合并捕获和抛出数据,以标识 RuntimeException 捕获for (ExceptionCaught caughtException : catchList) {
Set<String> thrownSet = new HashSet<String>();
for (ExceptionThrown thrownException : throwList) {
if (thrownException.offset >= caughtException.startOffset
&& thrownException.offset < caughtException.endOffset) {
thrownSet.add(thrownException.exceptionClass);
if (thrownException.exceptionClass.equals(caughtException.exceptionClass))
caughtException.seen = true;
}
}
int catchClauses = 0;
if (caughtException.exceptionClass.equals("java.lang.Exception")
&& !caughtException.seen) {
// Now we have a case where Exception is caught, but not thrown
boolean rteCaught = false;
for (ExceptionCaught otherException : catchList) {
if (otherException.startOffset == caughtException.startOffset
&& otherException.endOffset == caughtException.endOffset) {
catchClauses++;
if (otherException.exceptionClass.equals("java.lang.RuntimeException"))
rteCaught = true;
}
}
int range = caughtException.endOffset - caughtException.startOffset;
if (!rteCaught) {
bugReporter.reportBug(new BugInstance(this, "REC_CATCH_EXCEPTION",
NORM_PRIORITY)
.addClassAndMethod(this)
.addSourceLine(this, caughtException.sourcePC));
}
}
}
更多精彩
赞助商链接