ゼロ除算のチェックを挿入して、 fdiv演算を探すバイナリクラスを処理できます。
Java:
return x.getFloat() / f2;
javap出力:
0: aload_0
1: invokevirtual #22; //Method DivByZero$X.getFloat:()F
4: fload_1
5: fdiv
6: freturn
ゼロ除算のArithemticExceptionをスローする置換コード:
0: aload_1
1: invokevirtual #22; //Method DivByZero$X.getFloat:()F
4: fstore_2
5: fload_0
6: fconst_0
7: fcmpl
8: ifne 21
11: new #32; //class java/lang/ArithmeticException
14: dup
15: ldc #34; //String / by zero
17: invokespecial #36; //Method java/lang/ArithmeticException."<init>":(Ljava/lang/String;)V
20: athrow
21: fload_2
22: fload_0
23: fdiv
24: freturn
この処理は、 ASMなどのバイトコード操作APIを使用して実行できます。これは本当に些細なことではありませんが、ロケット科学でもありません。
(コードの動作を変更するのではなく)監視するだけの場合は、デバッガーを使用する方がよいでしょう。探しているものをキャッチする式をどのデバッガーで記述できるかはわかりませんが、独自のデバッガーを作成することは難しくありません。Sun JDKは、JPDAとその使用方法を示すサンプルコードを提供します(jdk / demo / jpda / examples.jarを解凍します)。
ローカルホストのソケットに接続するサンプルコード:
public class CustomDebugger {
public static void main(String[] args) throws Exception {
String port = args[0];
CustomDebugger debugger = new CustomDebugger();
AttachingConnector connector = debugger.getConnector();
VirtualMachine vm = debugger.connect(connector, port);
try {
// TODO: get & use EventRequestManager
vm.resume();
} finally {
vm.dispose();
}
}
private AttachingConnector getConnector() {
VirtualMachineManager vmManager = Bootstrap.virtualMachineManager();
for (Connector connector : vmManager.attachingConnectors()) {
System.out.println(connector.name());
if ("com.sun.jdi.SocketAttach".equals(connector.name())) {
return (AttachingConnector) connector;
}
}
throw new IllegalStateException();
}
private VirtualMachine connect(AttachingConnector connector, String port)
throws IllegalConnectorArgumentsException, IOException {
Map<String, Connector.Argument> args = connector.defaultArguments();
Connector.Argument pidArgument = args.get("port");
if (pidArgument == null) {
throw new IllegalStateException();
}
pidArgument.setValue(port);
return connector.attach(args);
}
}