静的分析を行うツールを試しています。このツールは、ソース コードではなくバイトコードで動作します。(ただし、ソースコードも持っています)。
このツールはバイトコードからいくつかの行番号を出力するので、ソース コードに戻す簡単な方法が必要です。Netbeans/Eclipse は常にこれを行っているため (含まれているライブラリのメソッドをクリックすると、IDE がソース (利用可能な場合) に移動します)、これが可能であることはわかっています。私はそれを行う方法を理解できませんでした。
例として、次の hello world プログラムを考えてみましょう。
package mypackage;
import java.io.*;
class MyMainClass {
public static void main(String[] args) {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String name0 = "Alice";
String name1 = "Bob";
try {
name0 = in.readLine();
}
catch(Exception e) {
System.out.println("Caught an exception!");
}
System.out.println("Hello " + name0 + "!");
System.out.println("Hello " + name1 + "!");
}
}
生成されたバイトコード (javap から取得) は次のとおりです。
Compiled from "MyMainClass.java"
class mypackage.MyMainClass extends java.lang.Object{
mypackage.MyMainClass();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2; //class java/io/BufferedReader
3: dup
4: new #3; //class java/io/InputStreamReader
7: dup
8: getstatic #4; //Field java/lang/System.in:Ljava/io/InputStream;
11: invokespecial #5; //Method java/io/InputStreamReader."<init>":(Ljava/io/InputStream;)V
14: invokespecial #6; //Method java/io/BufferedReader."<init>":(Ljava/io/Reader;)V
17: astore_1
18: ldc #7; //String Alice
20: astore_2
21: ldc #8; //String Bob
23: astore_3
24: aload_1
25: invokevirtual #9; //Method java/io/BufferedReader.readLine:()Ljava/lang/String;
28: astore_2
29: goto 42
32: astore 4
34: getstatic #11; //Field java/lang/System.out:Ljava/io/PrintStream;
37: ldc #12; //String Caught an exception!
39: invokevirtual #13; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
42: getstatic #11; //Field java/lang/System.out:Ljava/io/PrintStream;
45: new #14; //class java/lang/StringBuilder
48: dup
49: invokespecial #15; //Method java/lang/StringBuilder."<init>":()V
52: ldc #16; //String Hello
54: invokevirtual #17; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
57: aload_2
58: invokevirtual #17; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
61: ldc #18; //String !
63: invokevirtual #17; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
66: invokevirtual #19; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
69: invokevirtual #13; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
72: getstatic #11; //Field java/lang/System.out:Ljava/io/PrintStream;
75: new #14; //class java/lang/StringBuilder
78: dup
79: invokespecial #15; //Method java/lang/StringBuilder."<init>":()V
82: ldc #16; //String Hello
84: invokevirtual #17; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
87: aload_3
88: invokevirtual #17; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
91: ldc #18; //String !
93: invokevirtual #17; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
96: invokevirtual #19; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
99: invokevirtual #13; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
102: return
Exception table:
from to target type
24 29 32 Class java/lang/Exception
}
ツールの出力は次のようになります。
<mypackage.MyMainClass> 39, 69, 99
これらはバイトコードの行番号に対応しています。手動で、行がソース コードの次の行に対応している必要があることがわかります。
System.out.println("Caught an exception!");
System.out.println("Hello " + name0 + "!");
System.out.println("Hello " + name1 + "!");
ただし、このプロセスを自動化する必要があります。どんな助けでも大歓迎です。