Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4974302

inlined finally clauses confuse some debuggers

XMLWordPrintable

    • generic
    • solaris_8

        New code sequences first introduced in 1.4.x inlines some finally clauses.
        Apparently this confuses some debuggers (both tools and people), which used to
        expect the "ret" instruction to be considered part of the "return" statement.

        This can easily be fixed in javac by inserting a line number table
        entry following the inlined finalizer.

        Enclosed is part of a newsgroup conversation regarding this issue.


        Reply-To: "Chris Uppal" <###@###.###>
        Wrom: IYZUNNYCGPKYLEJGDGVCJVTLBXFGGMEPYOQKEDOTWFAOBUZXU
        Newsgroups: comp.lang.java.programmer
        References: <bt9a48$4g57n$###@###.###> <ezXJb.16795$###@###.###> <btbg2u$5bg5q$###@###.###> <3ff9643d$0$61071$###@###.###> <###@###.###> <###@###.###>
        Subject: Re: optimizing java compiler
        Date: Tue, 6 Jan 2004 09:08:54 -0000
        Xref: typhoon.sonic.net comp.lang.java.programmer:574466

        Neal Gafter wrote:

        > This isn't an optimization, it is simply an improved code generation
        > strategy. Why would you expect the debugger to go back to the return
        > statement? This is the first I've heard of someone being unhappy with
        > the new code sequence.

        I'm hesitant to mention this because I woudn't like to seem that I'm suggesting
        that this is in any way your fault or your problem, but the new code sequences
        have broken a few previously useful tools.

        For instance neither Jlint 2.3 nor JAD 1.5.8e2 will cope with the result of
        compiling either of the two appended classes with a 1.4.2 compiler. Perhaps
        the same code sequences will cause problems for other tools too.

        (I'd have emailed bug reports to the authors but I don't have an address for
        JAD, and I'm not sure that Jlint is actively maintained.)

            -- chris

        ========================

        import java.io.*;

        class BreakJlintAndJAD
        {
         public boolean
         save(String filename)
         {
          ObjectOutputStream out = null;
          try
          {
           out = new ObjectOutputStream(new FileOutputStream(filename));
           out.writeObject(new Object());
          }
          catch (Exception e)
          {
           return false;
          }
          finally
          {
           try
           {
            if (out != null)
             out.close();
           }
           catch (IOException e)
           {
            return false;
           }
          }

          return true;
         }
        }

        class BreakJlintAndJADAnotherWay
        {
         Object read()
         throws IOException, ClassNotFoundException
         {
          ObjectInputStream in = null;
          try
          {
           in = new ObjectInputStream(new FileInputStream("tmp"));
           return in.readObject();
          }
          finally
          {
           if (in != null)
            in.close();
          }
         }
        }

        =====================================================

        From the submitter:
        > Is that possible in the case of nested
        > try/catch/finally when both finallys are
        > inlined?
        > Granted, most programmers would have no
        > problem with this sequence. We were using a
        > debugger to demonstrate sequence of operations
        > with nested try/catch/finally to first-year
        > students in a class lecture. If the current
        > line jumps from the inner finally directly to
        > the outer, this is confusing to students,
        > especially if the exit point has scrolled off
        > the page. Even with a non-nested finally, it
        > is less clear if control does not return to
        > the return, continue, or break after the finally
        > block.

        From the evaluator:
        For the case of nested finally clauses, it is possible but probably something I would not want to do. The way to do it would be to generate a "nop" instruction between the finalizers with a line number table entry pointing to the return statement.

        From the submitter:

             I think it is more clear to go back to the
        exit, as a reminder of the type and target of
        the exit. Since this is how a non-inlined finally
        behaves, it would also be more consistent. For
        in-class demos, we are now just putting enough
        code in the finalizers to avoid the inlining.

        =====================================================

        Here is one that could be a bit confusing. When
        stepping, control goes from the if-statement
        directly to the finalizer without ever hitting
        the return statement.

        try {
           for(int i = 0; i < 3; i++) {
              if(i != 1)
                 ;
              else
                 return;
              }
           }
        finally {
           System.out.println("finally");
        }

        =====================================================

              ksrini Kumar Srinivasan
              gafter Neal Gafter (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: