1

I want to detect throw statements that occur from within a catch block. For instance:

try 
{
    def();
}
catch (IOException e)
{
    throw e;
}
catch (Exception e)
{
    throw new RuntimeException(e);
}

First, I was using Eclipse-JDT to detect these cases and it was quite simple, since I could traverse the Abstract Syntax Tree.

Now I have to use a framework (BAT - Bytecode Analysis Toolkit) that deals directly with the bytecode.

First of all, how the catch block is represented in the bytecode? And how can I detect a throw statement within it?

EijiAdachi
  • 441
  • 1
  • 3
  • 15

1 Answers1

3

Each method has an Exception Table that maps a range of instructions plus and exception type to an exception handler (it's entry point). This is not always easy to translate back to Java code. But in general, you will need to examine this table and then analyse reachable code from those entry points. All of that code belongs to a catch clause. Then it's just a matter of identifying athrow instructions.

Use javap or other good bytecode visualizer to play around and understand it better. Completing your code, compiling it, and subjecting it to javap produces:

public class Test extends java.lang.Object{
public Test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void def()   throws java.io.IOException;
  Code:
   0:   new     #2; //class java/io/IOException
   3:   dup
   4:   invokespecial   #3; //Method java/io/IOException."<init>":()V
   7:   athrow

public static void main(java.lang.String[])   throws java.io.IOException;
  Code:
   0:   invokestatic    #4; //Method def:()V
   3:   goto    19
   6:   astore_1
   7:   aload_1
   8:   athrow
   9:   astore_1
   10:  new     #6; //class java/lang/RuntimeException
   13:  dup
   14:  aload_1
   15:  invokespecial   #7; //Method java/lang/RuntimeException."<init>":(Ljava/lang/Throwable;)V
   18:  athrow
   19:  return
  Exception table:
   from   to  target type
     0     3     6   Class java/io/IOException

     0     3     9   Class java/lang/Exception


}

For method main we have 2 exception entry points ("targets"): 6 and 9. Following 6, we have an athrow at offset 8. Following the entry point at 9, we have an athrow at offset 18. That's it!

Mario Rossi
  • 7,651
  • 27
  • 37
  • The problem is that at the bytecode level there is no identification of the end of a catch block. In this manner, how can I distinguish between: catch(Exception e){ throw new RuntimeException(); } and catch(Exception e){} throw new RuntimeException(); In the first, the exception is thrown from within the catch block; in the second, the exception is thrown after the catch block. But at the bytecode level, both will have the `athrow` instruction after the `target` of the Exception-table. – EijiAdachi Aug 24 '13 at 02:48
  • 1
    Yes, that's a big problem and the reason why it's hard to translate them back into Java code. You need to do data flow analysis. Fortunately, a simple variant of it. Sorry I don't have a simpler answer. I hope you find it. – Mario Rossi Aug 24 '13 at 22:09