title: How to get the Java source code for a given bytecode position in an automated way?
body: <p>I am experimenting with a tool that does static analysis. The tool works on bytecode rather than source code. (However, I have the source code as well).</p>
  
  <p>The tool outputs some line numbers from the bytecode and now I need an easy way to map back to source code. Netbeans/Eclipse do this all the time (when I click on a method in an included library, the IDE takes me to the source (if it is available)), so I know this is possible. I just could not figure out a way to do it. </p>
  
  <p>As an example, consider the following hello world program:</p>
  
  <pre><code>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 + "!"); 
    }
  }
  </code></pre>
  
  <p>The generated bytecode (obtained from javap) is:</p>
  
  <pre><code>Compiled from "MyMainClass.java"
  class mypackage.MyMainClass extends java.lang.Object{
  mypackage.MyMainClass();
    Code:
     0:   aload_0
     1:   invokespecial   #1; //Method java/lang/Object."&lt;init&gt;":()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."&lt;init&gt;":(Ljava/io/InputStream;)V
     14:  invokespecial   #6; //Method java/io/BufferedReader."&lt;init&gt;":(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."&lt;init&gt;":()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."&lt;init&gt;":()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
  
  
  }
  </code></pre>
  
  <p>The output of the tool is something like:</p>
  
  <pre><code>&lt;mypackage.MyMainClass&gt; 39, 69, 99
  </code></pre>
  
  <p>These correspond to the bytecode line numbers. Manually I can figure out that the lines must correspond to the following lines in the source code:</p>
  
  <pre><code>System.out.println("Caught an exception!"); 
  System.out.println("Hello " + name0 + "!"); 
  System.out.println("Hello " + name1 + "!"); 
  </code></pre>
  
  <p>However, I need to automate this process. Any help would be appreciated. </p>