Estoy experimentando con una herramienta que realiza análisis estáticos. La herramienta funciona en bytecode en lugar de código fuente. (Sin embargo, también tengo el código fuente).¿Cómo obtener el código fuente de Java para una posición determinada de bytecode de forma automatizada?
La herramienta genera algunos números de línea del bytecode y ahora necesito una forma fácil de volver al código fuente. Netbeans/Eclipse hacen esto todo el tiempo (cuando hago clic en un método en una biblioteca incluida, el IDE me lleva a la fuente (si está disponible)), así que sé que esto es posible. Simplemente no pude encontrar una manera de hacerlo.
Como ejemplo, considere la siguiente hola programa mundial:
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 + "!");
}
}
El código de bytes generada (obtenido de javap) es:
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
}
La salida de la herramienta es algo así como:
<mypackage.MyMainClass> 39, 69, 99
Corresponden a los números de línea del bytecode. Manualmente puedo imaginar que las líneas deben corresponder a las siguientes líneas en el código fuente:
System.out.println("Caught an exception!");
System.out.println("Hello " + name0 + "!");
System.out.println("Hello " + name1 + "!");
Sin embargo, necesito para automatizar este proceso. Cualquier ayuda sería apreciada.
Puede usar el decompilador de datos para ese –