Bug 78021 - Injecting exception into while loop with break statement causes catch block to be ignored
Summary: Injecting exception into while loop with break statement causes catch block t...
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.2.1 M1   Edit
Hardware: PC Windows 2000
: P3 major (vote)
Target Milestone: ---   Edit
Assignee: Adrian Colyer CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-11-06 13:47 EST by Nigel Charman CLA
Modified: 2005-01-11 10:34 EST (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nigel Charman CLA 2004-11-06 13:47:16 EST
In order to test exception scenarios in an existing framework, I have
created an aspect to inject an exception.  The exception is injected into
some code running within a try/catch/finally block.  After the exception is
thrown, I am expecting control to pass to the catch block.  However, what
is happening is that the catch block code is not executed, control passes
through the finally block and the (undeclared) exception is thrown to the
calling method.

Here is a distilled test case:

public class MainClass {

       protected Integer counter;
       private int j;

       public static void main(String[] args) {

               MainClass mh = new MainClass();
               try {
                       mh.doSomething();
               } catch (Exception e) {
                       System.out.println("Exception thrown by
doSomething!!!!!");
                       e.printStackTrace();
               }
       }

       public void doSomething() {
               int i = 0;
               while (i++ < 1) {
                       counter=null;

                       try {
                               counter = getCounter();
                               if (counter == null) {
                                       break;
                               }

                               commit();
                       } catch (Throwable e) {
                               System.out.println("Caught exception " +
e);
                       } finally {
                               System.out.println("In finally block");
                       }
               }
       }

       protected Integer getCounter() {
               return new Integer(j++);
       }

       protected void commit() throws SQLException {
               System.out.println("Main.commit");
       }
}

The following aspect injects the exception:

public aspect SimpleExceptionThrowingAspect {

   pointcut commitOperation() : call (* MainClass+.commit(..));

   before() throws SQLException : commitOperation() {
        throw new SQLException("Dummy SQL Exception", "55102");
   }
}

Expected output is:
       Caught exception java.sql.SQLException: Dummy SQL Exception
       In finally block

Actual output is:
       In finally block
       Exception thrown by doSomething!!!!!
       java.sql.SQLException: Dummy SQL Exception        at
nz.govt.moh.test.SimpleExceptionThrowingAspect.ajc$before$nz_govt_moh_test_SimpleExceptionThrowingAspect$1$292c82f1(SimpleExceptionThrowingAspect.aj:10)

       at nz.govt.moh.test.MainClass.doSomething(MainClass.java:32)
       at nz.govt.moh.test.MainClass.main(MainClass.java:14)


Removing the "break;" statement from MainClass.java causes the expected
output to be produced.
Comment 1 Andrew Clement CLA 2005-01-10 06:13:08 EST
This is related to bug 79554 - they are both to do with us creating an incorrect
exception table for a woven method.  The exception table for the unwoven code is:

  Exception table:
   from   to  target type
     9    38    38   Class java/lang/Throwable
     9    29    64   any 
    32    61    64   any
    81    84    64   any

Once woven, this changes to:

  Exception table:
   from   to  target type
    87    90    70   any
    32    67    70   any
     9    44    44   Class java/lang/Throwable
     9    29    70   any

The inclusion of 'any' with a range that overlaps the 'Throwable' range is
causing the problem.  When the exception occurs, it is right in the overlap
range and so in the woven code we skip the catch block, do the finally stuff and
 rethrow the exception.

Comment 2 Andrew Clement CLA 2005-01-11 06:32:00 EST
When unpacking, we associate a priority with entries in the exception table. 
This priority can be used when writing the class out to ensure we don't break
the ordering carefully constructed by the compiler.  We currently ignore the
priority - leading to situations where sometimes entries for finally blocks
obscure entries for real catch blocks.  The implementation of the priority for
newly created exception handlers (created during weaving) doesn't seem quite
right as they are given either super high priority (Integer.MAX) or super low
priority (-1).  There are comments in the code (around
LazyMethodGen.insertHandler()) which suggest what the right long term
implementation would be but having spent the last day in the code, it is not
trivial and the simpler immediate fix of using the priorities fixes this bug and
the related 79954.

We can do the full implementation of the priority work when (if?) someone finds
a situation that the current algorithm doesn't cope with.

Fix checked in - waiting for build.
Comment 3 Andrew Clement CLA 2005-01-11 10:34:57 EST
Fix available:

BUILD COMPLETE -  build.429
Date of build: 01/11/2005 11:52:16
Time to build: 103 minutes 38 seconds
Last changed: 01/11/2005 11:22:16
Last log entry: Fixes for 78021, 79554 - both to do with us breaking the
exception table for a method on weaving *if* finally blocks are involved.
Latest good AspectJ jar available at:
download.eclipse.org/technology/ajdt/dev/aspectj-DEVELOPMENT.jar