JRuby (please use github issues at http://bugs.jruby.org)
  1. JRuby (please use github issues at http://bugs.jruby.org)
  2. JRUBY-3959

backtrace reported by NativeException incorrect under certain scenarios

    Details

    • Type: Bug Bug
    • Status: Resolved Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None
    • Environment:
      java 1.6.0_10, ubuntu 8.10, x86
    • Testcase included:
      yes
    • Patch Submitted:
      Yes
    • Number of attachments :
      2

      Description

      NativeException backtraces have been greatly improved by JRUBY-3890. However, there are a few scenarios in which the backtrace reported is either incorrect or causes JRuby to crash (see examples section below).

      I've included a test case for each of the examples as well as a patch to address the issues presented.

      Examples

      Example 1

      example_1.rb
      def example1
        x = java.lang.String.new("")
        x.charAt(12)
      rescue Exception => ex
        puts ex.backtrace.join("\n")
      end
      example1
      

      If you save the above to a file and then run the file, the backtrace reported will look like:

      ./jruby -rjava example_1.rb
        java.lang.StringIndexOutOfBoundsException: String index out of range: 12
        java/lang/String.java:687:in `charAt'
        example_1.rb:2:in `example1'
        example_1.rb:8
      

      Instead it should look like the below. The above backtrace incorrectly reports the error occuring on line 2 of example_1.rb instead of line 3.

      ./jruby -rjava example_1.rb
        java.lang.StringIndexOutOfBoundsException: String index out of range: 12
        java/lang/String.java:687:in `charAt'
        example_1.rb:3:in `example1'
        example_1.rb:8
      

      Example 2

      example_2.rb
      class Example2
        def initialize
          @x = java.lang.String.new("blah")
        end
      
        def raise_native_exception
          @x.charAt(12)
        rescue Exception => ex
          puts ex.message
          puts ex.backtrace.join "\n"
        end
      end
      
      e = Example2.new
      e.raise_native_exception
      

      Produces the following output:

      jruby -rjava example_2.rb
        java.lang.StringIndexOutOfBoundsException: String index out of range: 12
        java/lang/String.java:687:in `charAt'
        example_2.rb:15:in `raise_native_exception'
        example_2.rb:16
      

      Instead it should look like below. The difference is the 2nd last line. The error occurred on line 8 not on line 15.

      /jruby -rjava example_2.rb
        java.lang.StringIndexOutOfBoundsException: String index out of range: 12
        java/lang/String.java:687:in `charAt'
        example_2.rb:8:in `raise_native_exception'
        example_2.rb:16
      

      Example 3

      example_3.rb
      def example_3
        java.lang.StringBuilder.new(-1)
      rescue Exception => ex
        puts ex.message
        puts ex.backtrace.join("\n")
      end
      example_3
      

      Produces the following output:

      jruby -rjava example_3.rb
        java.lang.NegativeArraySizeException: null
        java/lang/AbstractStringBuilder.java:45:in `<init>'
        java/lang/StringBuilder.java:80:in `<init>'
        sun/reflect/NativeConstructorAccessorImpl.java:-2:in `newInstance0'
        sun/reflect/NativeConstructorAccessorImpl.java:39:in `newInstance'
        sun/reflect/DelegatingConstructorAccessorImpl.java:27:in `newInstance'
        java/lang/reflect/Constructor.java:513:in `newInstance'
        org/jruby/javasupport/JavaConstructor.java:275:in `newInstanceDirect'
        /home/teys/dev/jruby/lib/ruby/site_ruby/shared/builtin/javasupport/java.rb:51:in `new_proxy'
        example_3.rb:2:in `example_3'
        example_3.rb:7
      

      Instead it should look like the below.

      jruby -rjava example_3.rb
        java.lang.NegativeArraySizeException: null
        java/lang/AbstractStringBuilder.java:45:in `<init>'
        java/lang/StringBuilder.java:80:in `<init>'
        example_3.rb:2:in `new_proxy'
        example_3.rb:2:in `example_3'
        example_3.rb:7
      

      Whether or not 'new_proxy' should be included in the backtrace is debatable.

      Example 4

      Finally example 4 will presently crash JRuby.

      Bar.java
      package org.jruby.test;
      
      public class Bar
      {
        public static void throwExceptionWithDeepStackTrace(int depth)
        {
          foo(depth);
        }
        
        private static void foo(int depth)
        {
          if (depth == 0) throw new RuntimeException("foo");
          foo(--depth);
        }
      }
      
      example_4.rb
      def example_4
        Java::org.jruby.test.Bar.throwExceptionWithDeepStackTrace(1025)
      rescue Exception => ex
        puts ex.message
        puts ex.backtrace.join("\n")
      end
      
      example_4
      

      To run the above example I had to copy Bar.java to jruby/test/org/jruby/test/Bar/java and example_4.rb to the jruby folder and then run the following commands:

      ant clean compile compile-test
      jar cf build/jruby-test-classes.jar -C build/classes/test .
      bin/jruby -J-cp build/jruby-test-classes.jar -rjava example_4.rb
      NativeException.java:121:in `trimStackTrace': java.lang.ArrayIndexOutOfBoundsException: 1024
              from RaiseException.java:99:in `createNativeRaiseException'
              from JavaSupport.java:199:in `createRaiseException'
              from JavaSupport.java:195:in `handleNativeException'
              from JavaCallable.java:170:in `handleInvocationTargetEx'
              from JavaMethod.java:459:in `invokeDirectWithExceptionHandling'
              from JavaMethod.java:356:in `invokeStaticDirect'
              from StaticMethodInvoker.java:48:in `call'
              from CachingCallSite.java:310:in `cacheAndCall'
              from CachingCallSite.java:149:in `call'
              from example_4.rb:2:in `method__0$RUBY$example_4'
              from example_4#example_4:-1:in `call'
              from example_4#example_4:-1:in `call'
              from CachingCallSite.java:290:in `cacheAndCall'
              from CachingCallSite.java:109:in `call'
              from example_4.rb:8:in `__file__'
              from example_4.rb:-1:in `load'
              from Ruby.java:628:in `runScript'
              from Ruby.java:550:in `runNormally'
              from Ruby.java:396:in `runFromMain'
              from Main.java:272:in `run'
              from Main.java:117:in `run'
              from Main.java:97:in `main'
      
      1. fix-backtrace-issues.patch
        17 kB
        Andrew Davey
      2. test_case.patch
        9 kB
        Andrew Davey

        Activity

        Hide
        Charles Oliver Nutter added a comment -

        Nice, thank you for the patch! We'll review and apply.

        Show
        Charles Oliver Nutter added a comment - Nice, thank you for the patch! We'll review and apply.
        Hide
        Thomas E Enebo added a comment -

        Sorry we will get this in early in 1.5 dev cycle since we ran out of time for 1.4.

        Show
        Thomas E Enebo added a comment - Sorry we will get this in early in 1.5 dev cycle since we ran out of time for 1.4.
        Thomas E Enebo made changes -
        Field Original Value New Value
        Assignee Thomas E Enebo [ enebo ]
        Hide
        Thomas E Enebo added a comment -

        whoops forgot to unmark for 1.4

        Show
        Thomas E Enebo added a comment - whoops forgot to unmark for 1.4
        Thomas E Enebo made changes -
        Fix Version/s JRuby 1.4 [ 15285 ]
        Fix Version/s JRuby 1.x+ [ 13421 ]
        Hide
        Charles Oliver Nutter added a comment -

        Looks like this is working now, so I added your test in f5034c9.

        Show
        Charles Oliver Nutter added a comment - Looks like this is working now, so I added your test in f5034c9.
        Charles Oliver Nutter made changes -
        Fix Version/s JRuby 1.x+ [ 13421 ]
        Assignee Charles Oliver Nutter [ headius ]
        Status Open [ 1 ] Resolved [ 5 ]
        Resolution Fixed [ 1 ]
        Fix Version/s JRuby 1.5 [ 15792 ]
        Hide
        Charles Oliver Nutter added a comment -

        Incorrectly resolved this bug.

        Show
        Charles Oliver Nutter added a comment - Incorrectly resolved this bug.
        Charles Oliver Nutter made changes -
        Status Resolved [ 5 ] Reopened [ 4 ]
        Resolution Fixed [ 1 ]
        Charles Oliver Nutter made changes -
        Fix Version/s JRuby 1.5 [ 15792 ]
        Hide
        Charles Oliver Nutter added a comment -

        This is as fixed as it's going to be for now. Native Java exceptions will report their own stack traces in 1.7.

        Show
        Charles Oliver Nutter added a comment - This is as fixed as it's going to be for now. Native Java exceptions will report their own stack traces in 1.7.
        Charles Oliver Nutter made changes -
        Status Reopened [ 4 ] Resolved [ 5 ]
        Resolution Fixed [ 1 ]

          People

          • Assignee:
            Charles Oliver Nutter
            Reporter:
            Andrew Davey
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: