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

assignment to Java::byte[] creates range error for values greater than 127

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: JRuby 1.6RC1, JRuby 1.6RC2, JRuby 1.6RC3, JRuby 1.6
    • Fix Version/s: JRuby 1.6.1
    • Component/s: Java Integration
    • Labels:
      None
    • Environment:
      Windows XP
    • Number of attachments :
      1

      Description

      In previous versions, the assignement of a Fixnum upto 255 was accepted in assignement, since 1.6 this creates a range error.

      Not sure if this behaviour is intneded. I can't find any documentation about this change. I know that Java::byte is signed -128..127 but sofar when bridging Ruby and Java this form of asignment was accepted.

      Below : test case is shown.

      ---------------------

      Welcome to the JRuby IRB Console [1.5.6]

      irb(main):001:0> b = Java::byte[6].new
      #<#<Class:01x1b19753>:0x45ce17>
      irb(main):002:0> b[0] = 245
      245
      irb(main):003:0>

      Welcome to the JRuby IRB Console [1.6.0.RC1]

      irb(main):001:0> b = Java::byte[6].new
      #<#<Class:0x101f35e30>:0xaccd65>
      irb(main):002:0> b[0] = 245
      RangeError: too big for byte: 245
      from org/jruby/java/proxies/ArrayJavaProxy.java:84:in `op_aset'
      from (irb):2:in `evaluate'
      from org/jruby/RubyKernel.java:1091:in `eval'
      from C:/jruby-1.6.0.RC1/lib/ruby/1.8/irb.rb:158:in `eval_input'
      from C:/jruby-1.6.0.RC1/lib/ruby/1.8/irb.rb:271:in `signal_status'
      from C:/jruby-1.6.0.RC1/lib/ruby/1.8/irb.rb:155:in `eval_input'
      from org/jruby/RubyKernel.java:1421:in `loop'
      from org/jruby/RubyKernel.java:1194:in `rbCatch'
      from C:/jruby-1.6.0.RC1/lib/ruby/1.8/irb.rb:154:in `eval_input'
      from C:/jruby-1.6.0.RC1/lib/ruby/1.8/irb.rb:71:in `start'
      from org/jruby/RubyKernel.java:1194:in `rbCatch'
      from C:/jruby-1.6.0.RC1/lib/ruby/1.8/irb.rb:70:in `start'
      irb(main):003:0>

      1. to_jb.rb
        0.7 kB
        John Bebbington

        Activity

        Hide
        Charles Oliver Nutter added a comment -

        I'm on the fence about this one. For the other types, we also throw a hard error if the incoming value is outside the signed range of the target. This is sometimes a hassle, but if we tried to guess what to do we'd be wrong half the time.

        In this case, however, we're talking about bytes, which are very commonly used in their unsigned form. Indeed, we return unsigned byte values from String and IO methods that return bytes, so not being able to stuff a signed Fixnum in the range 0..255 into an 8-bit Java byte is definitely problematic.

        Perhaps the "right" way to do this would be to convert values in the range 128..255 to their signed bits equivalent and allow them through? I hate adding exceptions like this, but if it's not there it's a bit painful to pass a full range of 8-bit values to Java.

        What do others think?

        In the interim you could simply convert values in that range to their signed equivalent and it should work...

        Show
        Charles Oliver Nutter added a comment - I'm on the fence about this one. For the other types, we also throw a hard error if the incoming value is outside the signed range of the target. This is sometimes a hassle, but if we tried to guess what to do we'd be wrong half the time. In this case, however, we're talking about bytes, which are very commonly used in their unsigned form. Indeed, we return unsigned byte values from String and IO methods that return bytes, so not being able to stuff a signed Fixnum in the range 0..255 into an 8-bit Java byte is definitely problematic. Perhaps the "right" way to do this would be to convert values in the range 128..255 to their signed bits equivalent and allow them through? I hate adding exceptions like this, but if it's not there it's a bit painful to pass a full range of 8-bit values to Java. What do others think? In the interim you could simply convert values in that range to their signed equivalent and it should work...
        Hide
        John Bebbington added a comment - - edited

        Perhaps adding to_jb to Fixnum would be a solution for both sides of the fence:

        class Fixnum
          # to Java byte
          # takes a Ruby Fixnum and returns the value as signed byte range -128..128 (Java byte).
          # rasies RangeError
          def to_jb
             raise RangeError,"too big for Java byte: #{self}" if (self < -128 || self > 255) 
            if self > 127 then
               return self - 256
            else 
              return self
              end
          end
        end
        
        Show
        John Bebbington added a comment - - edited Perhaps adding to_jb to Fixnum would be a solution for both sides of the fence: class Fixnum # to Java byte # takes a Ruby Fixnum and returns the value as signed byte range -128..128 (Java byte ). # rasies RangeError def to_jb raise RangeError, "too big for Java byte : #{self}" if (self < -128 || self > 255) if self > 127 then return self - 256 else return self end end end
        Hide
        John Bebbington added a comment -

        to_jb added to Fixnum
        Also testcase works for both JRuby 1.5.6 and 1.6.0

        Show
        John Bebbington added a comment - to_jb added to Fixnum Also testcase works for both JRuby 1.5.6 and 1.6.0
        Hide
        Charles Oliver Nutter added a comment -

        I opted to add two methods to byte[] directly: ubyte_set and ubyte_get. They work pretty much like you'd expect:

        ary = Java::byte[1].new
        ary.ubyte_set(0, 0xFF)
        ary.ubyte_get(0) # => 0xFF
        ary[0] # => -1
        ary[0] = 0xFF # => RangeError
        

        Your option was certainly a reasonable one, but added the overhead of constructing an intermediate java.lang.Byte that also gets wrapped in a proxy object. The ubyte_set and ubyte_get options will still deal directly with Fixnum, and only have the overhead of Fixnum math and a bit of Ruby code.

        If you see that the overhead is too much, we can look at implementing it native. Let us know (and probably file a separate bug).

        Show
        Charles Oliver Nutter added a comment - I opted to add two methods to byte[] directly: ubyte_set and ubyte_get. They work pretty much like you'd expect: ary = Java::byte[1].new ary.ubyte_set(0, 0xFF) ary.ubyte_get(0) # => 0xFF ary[0] # => -1 ary[0] = 0xFF # => RangeError Your option was certainly a reasonable one, but added the overhead of constructing an intermediate java.lang.Byte that also gets wrapped in a proxy object. The ubyte_set and ubyte_get options will still deal directly with Fixnum, and only have the overhead of Fixnum math and a bit of Ruby code. If you see that the overhead is too much, we can look at implementing it native. Let us know (and probably file a separate bug).
        Hide
        Charles Oliver Nutter added a comment -

        commit 270179091a19063bdd88507cc3ee3d89da1c4127
        Author: Charles Oliver Nutter <headius@headius.com>
        Date: Thu Mar 31 20:12:45 2011 -0500

        Fix JRUBY-5597: assignment to Java::byte[] creates range error for values greater than 127

        • Add ubyte_set and ubyte_get to Java byte[] to allow setting and getting unsigned bytes.
        Show
        Charles Oliver Nutter added a comment - commit 270179091a19063bdd88507cc3ee3d89da1c4127 Author: Charles Oliver Nutter <headius@headius.com> Date: Thu Mar 31 20:12:45 2011 -0500 Fix JRUBY-5597 : assignment to Java::byte[] creates range error for values greater than 127 Add ubyte_set and ubyte_get to Java byte[] to allow setting and getting unsigned bytes.
        Hide
        John Bebbington added a comment -

        I'm happy with your solution. It makes sense.

        Show
        John Bebbington added a comment - I'm happy with your solution. It makes sense.

          People

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

            Dates

            • Created:
              Updated:
              Resolved: