如何检测字节码以判断何时执行 catch 子句?
How to instrument the byte code to tell when a catch clause is being executed?
基于Brett Walker's comment to this ,我想知道如何实现。
"If you want to fail the unit test, in the most general sense, when ever a catch clause is executed by the code in this method you are going to have to instrument the byte code to tell you when a catch clause is being executed. This is a complex task. I would not recommend this."
我如何测试某个方法是否执行了 catch 子句? (下面示例中的isCatched()
。
假设我有以下 class:
public class A {
public void method() {
try {
// some code that may or may not throw an exception
} catch(Exception e) {
// do nothing
}
}
}
然后在其他地方:
public class CatchTester {
private A a;
public CatchTester(A a) {
this.a = a;
}
public boolean isCatched() {
// how to do this?
}
}
有两种方法,都需要了解如何操作 Java 字节码。 ASM exist for making manipulating byte codes a little easier. One would then wire in a Java Agent 等工具或编写自定义 class 加载程序,在将 class 字节加载到 JVM 时对其进行修改。
这种方法的一个很好的例子是 https://github.com/google/allocation-instrumenter。 Allocation-Instrumenter 修改了 class 的字节码,以便可以注册一个回调方法,只要发生对象分配就会调用该回调方法。想象一个用于 try/catch 仪器的类似库并不难。
如果你想通过 Instrumentation 检测某个代码是否被执行,你必须修改代码,注入某种日志代码,它会有效地回调一个方法来记录这个代码被命中的事实。然后你可以在检查方法returns.
后立即检查是否存在这样的记录
虽然在每个异常处理程序的开头插入这样的日志记录代码并不难,但问题是在字节码级别上,catch
、[=11]之间没有区别=] 或 try(…)
子句。他们最终都定义了异常处理程序,其中一些可能会重新抛出捕获的异常。如果你想排除重新抛出异常的处理程序,你必须跟踪每条可能的代码路径,从异常处理程序的入口开始,检查它是否以正常完成结束或抛出异常,无论是捕获的还是另一个新构造的.
如果只想知道any catch
子句是否执行过,情况就简单多了。如果在 method()
执行期间抛出异常但 method()
正常完成,即调用者未收到异常,则 必须 已经有异常处理程序已执行。
基于Brett Walker's comment to this
"If you want to fail the unit test, in the most general sense, when ever a catch clause is executed by the code in this method you are going to have to instrument the byte code to tell you when a catch clause is being executed. This is a complex task. I would not recommend this."
我如何测试某个方法是否执行了 catch 子句? (下面示例中的isCatched()
。
假设我有以下 class:
public class A {
public void method() {
try {
// some code that may or may not throw an exception
} catch(Exception e) {
// do nothing
}
}
}
然后在其他地方:
public class CatchTester {
private A a;
public CatchTester(A a) {
this.a = a;
}
public boolean isCatched() {
// how to do this?
}
}
有两种方法,都需要了解如何操作 Java 字节码。 ASM exist for making manipulating byte codes a little easier. One would then wire in a Java Agent 等工具或编写自定义 class 加载程序,在将 class 字节加载到 JVM 时对其进行修改。
这种方法的一个很好的例子是 https://github.com/google/allocation-instrumenter。 Allocation-Instrumenter 修改了 class 的字节码,以便可以注册一个回调方法,只要发生对象分配就会调用该回调方法。想象一个用于 try/catch 仪器的类似库并不难。
如果你想通过 Instrumentation 检测某个代码是否被执行,你必须修改代码,注入某种日志代码,它会有效地回调一个方法来记录这个代码被命中的事实。然后你可以在检查方法returns.
后立即检查是否存在这样的记录虽然在每个异常处理程序的开头插入这样的日志记录代码并不难,但问题是在字节码级别上,catch
、[=11]之间没有区别=] 或 try(…)
子句。他们最终都定义了异常处理程序,其中一些可能会重新抛出捕获的异常。如果你想排除重新抛出异常的处理程序,你必须跟踪每条可能的代码路径,从异常处理程序的入口开始,检查它是否以正常完成结束或抛出异常,无论是捕获的还是另一个新构造的.
如果只想知道any catch
子句是否执行过,情况就简单多了。如果在 method()
执行期间抛出异常但 method()
正常完成,即调用者未收到异常,则 必须 已经有异常处理程序已执行。