Details
-
Type:
Bug
-
Status:
Resolved
-
Priority:
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 :
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
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
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
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.
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); } }
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'
Nice, thank you for the patch! We'll review and apply.