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

Stack trace has invalid line numbers

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 8
    • 7
    • tools
    • b06
    • x86
    • linux
    • Verified

      FULL PRODUCT VERSION :
      java version "1.7.0-ea"
      Java(TM) SE Runtime Environment (build 1.7.0-ea-b131)
      Java HotSpot(TM) 64-Bit Server VM (build 21.0-b02, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      N/A observed on windows and linux

      A DESCRIPTION OF THE PROBLEM :
      linenumbertable in compiled code only has line numbers for starts of statements. When a statement is using method chaining or other "fluent Interface" style API's a single statement can span tens of lines and contain hundreds on method invocations.

      Currently an exception throw from within any of these methods will have the linenumber of the first line of the enclosing statement which makes it very hard to debug which method call is having a problem.

      linnumbertable should have correct line numbers for every method invocation.


      This is making it very difficult to develop a fluent interface API (for swing layouts) because you cannot associate a particular bad use of the API with the problematic code. I have layouts that are 30 lines long with maybe 60 method invocations of may 15 different methods. When one is passed invalid arguments there is no hint as to which of many invocations of that method it is.



      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile and run this test class

      (it is line number sensitive so make sure no lines get added or removed)

      --------------
      package linenumbertable;
      public class Main {
          public static void main(String[] args) {
              Main m = new Main();
              m.nest(5);
              m.nest(6, m.nest(6),m.nest(6),
                  m.nest(7),
                  m.nest(8,
                      m.nest(9)
                  )
              );
          }

          public Main nest(int line, Main... args) {
              IllegalStateException e = new IllegalStateException("Exception line number in main() incorrect - expected " + line);;
              if(e.getStackTrace()[1].getLineNumber() != line) throw e;
              System.out.format("Line number %d correct%n", line);
              return null;
          }
      }
      ----------------

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Line number 5 correct
      Line number 6 correct
      Line number 6 correct
      Line number 7 correct
      Line number 9 correct
      Line number 8 correct
      Line number 6 correct

      ACTUAL -
      Line number 5 correct
      Line number 6 correct
      Line number 6 correct
      Exception in thread "main" java.lang.IllegalStateException: Exception line number in main() incorrect - expected 7
              at linenumbertable.Main.nest(Main.java:15)
              at linenumbertable.Main.main(Main.java:6)

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package linenumbertable;
      public class Main {
          public static void main(String[] args) {
              Main m = new Main();
              m.nest(5);
              m.nest(6, m.nest(6),m.nest(6),
                  m.nest(7),
                  m.nest(8,
                      m.nest(9)
                  )
              );
          }

          public Main nest(int line, Main... args) {
              IllegalStateException e = new IllegalStateException("Exception line number in main() incorrect - expected " + line);;
              if(e.getStackTrace()[1].getLineNumber() != line) throw e;
              System.out.format("Line number %d correct%n", line);
              return null;
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      no workaround - but have a patch for the compiler. Will submit via openjdk compiler project

      Modify Gen.java add 2 lines to visitApply

          public void visitApply(JCMethodInvocation tree) {
              // Generate code for method.
              Item m = genExpr(tree.meth, methodType);
              // Generate code for all arguments, where the expected types are
              // the parameters of the method's external type (that is, any implicit
              // outer instance of a super(...) call appears as first parameter).
              genArgs(tree.args,
                      TreeInfo.symbol(tree.meth).externalType(types).getParameterTypes());
      + code.statBegin(tree.pos);
      + code.markStatBegin();
              result = m.invoke();
          }

            ksrini Kumar Srinivasan
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: