Giter VIP home page Giter VIP logo

jrjackson's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

jrjackson's Issues

ArgumentError on invalid byte sequence in UTF-8

The code:

JrJackson::Json.load("\x82\xAC\xEF")

produces this error:

ArgumentError: invalid byte sequence in UTF-8
    from org/jruby/RubyRegexp.java:1674:in `=~'
    from org/jruby/RubyString.java:1697:in `=~'
    from /Users/rwz/.rbenv/versions/jruby-1.7.9/lib/ruby/gems/shared/gems/jrjackson-0.2.5/lib/jrjackson/jrjackson.rb:17:in `load'
    from (irb):3:in `evaluate'
    from org/jruby/RubyKernel.java:1119:in `eval'
    from org/jruby/RubyKernel.java:1519:in `loop'
    from org/jruby/RubyKernel.java:1282:in `catch'
    from org/jruby/RubyKernel.java:1282:in `catch'
    from /Users/rwz/.rbenv/versions/jruby-1.7.9/bin/irb:13:in `(root)'

Expected result would be to raise JrJackson::ParseError

License?

I see that Jackson has a dual license with your choice between Apache 2.0 and GNU Lesser GPL 2.1.
Would it be possible for you to include a license for your wrapper library?

Add an option to serialize BigDecimal as String

Rails serialize BigDecimal as String. If we want to use JrJackson as drop in replacement, we need an option to serialize BigDecimal as String.

Test case:

require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'activesupport'
  gem 'jrjackson'
end

require 'minitest/autorun'

class MyTest < Minitest::Test
  def test_should_be_true
    require 'active_support/core_ext/object/json'
    obj = {number: BigDecimal.new('123.45')}
    assert_equal JSON.dump(obj), JrJackson::Json.dump(obj)
  end
end

Output:

  1) Failure:
MyTest#test_should_be_true [test.rb:15]:
Expected: "{\"number\":\"123.45\"}"
  Actual: "{\"number\":123.45}"

Arbitrary nested objects are not serialized

JrJackson's behaviour differs from the JSON gem when serializing arbitrary objects. In some scenarios this prevents it from being a drop-in replacement in MultiJson. I stumbled upon this when serializing dates. Here is an example interpreter session...

[1] pry(main)> JrJackson::Json.dump(Time.now)
=> "\"2013-10-08T17:08:01+03:00\""
[2] pry(main)> JrJackson::Json.dump(DateTime.now)
=> "\"2013-10-08T17:08:04+03:00\""
[3] pry(main)> JrJackson::Json.dump(Time.zone.now)
=> "\"2013-10-08T14:08:16.005Z\""
[4] pry(main)> JrJackson::Json.dump("now" => Time.now)
JrJackson::ParseError: (was java.lang.NullPointerException) (through reference chain: org.jruby.RubyHash["now"])
from com/jrjackson/JrJacksonRaw.java:155:in `generate'
[5] pry(main)> JrJackson::Json.dump("now" => DateTime.now)
JrJackson::ParseError: Failed to load class 'org.jruby.RubyObject$Access4JacksonSerializer': com/fasterxml/jackson/module/afterburner/ser/BeanPropertyAccessor
from com/jrjackson/JrJacksonRaw.java:155:in `generate'
[6] pry(main)> JrJackson::Json.dump("now" => Time.zone.now)
JrJackson::ParseError: Failed to load class 'org.jruby.RubyObject$Access4JacksonSerializer': com/fasterxml/jackson/module/afterburner/ser/BeanPropertyAccessor
from com/jrjackson/JrJacksonRaw.java:155:in `generate'

Flat objects work properly in JrJackson (the code for this is implemented in ruby), but dumping fails once the object is nested inside an array or hash (this happens in java). Here is the output from the JSON gem for comparison . It does successfully serialize the nested dates:

[1] pry(main)> JSON.dump(Time.now)
=> "\"2013-10-08T17:14:47+03:00\""
[2] pry(main)> JSON.dump("now" => Time.now)
=> "{\"now\":\"2013-10-08T17:14:57+03:00\"}"

It seems that the difference in behaviour comes from JrJackson not falling back to the to_json method if the object is inside a hash or an array. Here is an example:

[1] pry(main)> class Asd
[1] pry(main)*   def to_json(options = nil)
[1] pry(main)*     '{"asd": "asd"}'
[1] pry(main)*   end
[1] pry(main)* end
=> nil
[2] pry(main)> asd = Asd.new
=> #<Asd:0x41930b5f>
[3] pry(main)> JSON.dump("someting" => asd)
=> "{\"someting\":{\"asd\": \"asd\"}}"
[4] pry(main)> JrJackson::Json.dump("someting" => asd)
JrJackson::ParseError: Failed to load class 'org.jruby.RubyObject$Access4JacksonSerializer': com/fasterxml/jackson/module/afterburner/ser/BeanPropertyAccessor
from com/jrjackson/JrJacksonRaw.java:155:in `generate'

jrjackson improperly dumps BSON::ObjectId

Using jrjackson 0.3.4 and multi_json:

BSON::ObjectId defines both #to_a and #to_json. AnySerializer prefers to_a over to_json, which results in object IDs being dumped as byte arrays rather than hex strings.

It seems incorrect that AnySerializer should prefer anything over to_json, since that should be canonically what the representation of the object should be, no?

:001 > i = Page.first._id
 => BSON::ObjectId('55fac1442f904994449b68d8')

:002 > JSON.dump(i)
 => "\"55fac1442f904994449b68d8\""
:003 > MultiJson.dump(i)
 => "\"55fac1442f904994449b68d8\""

:005 > JSON.dump({_id: i})
 => "{\"_id\":\"55fac1442f904994449b68d8\"}"
:004 > MultiJson.dump({_id: i})
 => "{\"_id\":[85,250,193,68,47,144,73,148,68,155,104,216]}"

Repro:

# Gemfile
source "https://rubygems.org"
gem "mongo", "~> 1.0"
gem "jrjackson"

# Repro:
require 'mongo'
require 'jrjackson'

id = BSON::ObjectId.new
JrJackson::Json.dump({_id: id})

JrJackson::Json does not completely implement the JSON interface

The JrJackson::Json module implements dump and load but doesn’t implement other methods defined on the JSON module in the Ruby standard library (e.g. #pretty_generate). Furthermore, the module doesn’t contain all the classes defined within the module. This is an issue because you assign the module JrJackson::Json to JSON.

# lib/jrjackson/jrjackson.rb:53
JSON = JrJackson::Json unless defined?(JSON)

The can lead to errors, for example, if someone attempts to rescue JSON::ParserError.

uninitialized constant JrJackson::Json::ParserError

See intridea/multi_json#40.

I’m not sure if you intend to continue supporting Ruby 1.8.7, but now that JSON is part of the standard library, it may make sense to always require 'json' and then just redefine dump and load on the existing JSON module instead of overwriting the entire module.

Or, simply don’t assign JrJackson::Json to JSON.

ArgumentError on StringIO

This code

require "stringio"
input = StringIO.new('{"foo":"bar"}')
JrJackson::Json.load(input)

produces this exception:

ArgumentError: Unsupported source. This method accepts String or IO
    from com/jrjackson/JrJacksonRaw.java:95:in `parse_str'
    from /Users/rwz/.rbenv/versions/jruby-1.7.9/lib/ruby/gems/shared/gems/jrjackson-0.2.5/lib/jrjackson/jrjackson.rb:30:in `load'
    from (irb):7:in `evaluate'
    from org/jruby/RubyKernel.java:1119:in `eval'
    from org/jruby/RubyKernel.java:1519:in `loop'
    from org/jruby/RubyKernel.java:1282:in `catch'
    from org/jruby/RubyKernel.java:1282:in `catch'
    from /Users/rwz/.rbenv/versions/jruby-1.7.9/bin/irb:13:in `(root)'

One may expect StringIO object be handled correctly especially since JrJackson clams to be compatible with IO objects.

inconsistency with Time serialization

Time object will be handled by to_s at https://github.com/guyboertje/jrjackson/blob/master/lib/jrjackson/jrjackson.rb#L45

JrJackson::Json.dump(Time.now)
=> "2014-06-10 23:19:37 -0400"

Time object will be handled by Jackson as a Java::JavaUtil::Date

JrJackson::Json.dump([Time.now])
=> "[\"2014-06-10 23:24:11 EDT\"]"

Time object will be handled by Jackson as a Java::JavaUtil::Date

JrJackson::Raw.generate(Time.now)
=> "\"2014-06-10 23:25:04 EDT\""

Wouldn't it be better to also add Time as a shortcut to JrJackson::Raw.generate at https://github.com/guyboertje/jrjackson/blob/master/lib/jrjackson/jrjackson.rb#L36 ?

Gem release of JrJackson is potentially larger than need be

Hi!

I noticed the most recent version of jrjackson (0.2.4) is 35.1MB on rubygems.org: http://rubygems.org/gems/jrjackson/versions/0.2.4. I unpacked the gem and looked at the output.

It appears like some savings could be made by excluding the benchmarking folder when building the gem?

 35M    ./benchmarking/fixtures
 60K    ./benchmarking/individual
 35M    ./benchmarking
 22M    ./lib/jrjackson/jars
 22M    ./lib/jrjackson
 22M    ./lib
4.0K    ./profiling
 52K    ./src/main/java/com/jrjackson
 52K    ./src/main/java/com
 52K    ./src/main/java
 52K    ./src/main
4.0K    ./src/test/java/com/jrjackson/jruby
4.0K    ./src/test/java/com/jrjackson
4.0K    ./src/test/java/com
4.0K    ./src/test/java
4.0K    ./src/test
 56K    ./src
4.0K    ./test
 58M    .

ArgumentError - Unsupported source - JRuby

When deploying a JRuby (1.7.5) on Rails (3.2.11) app as a WAR to Tomcat (7.0.40) using jrjackson 0.2.0 and then jrjackson 0.2.5, I'm seeing the following errors when doing stuff with JSON:

org.jruby.exceptions.RaiseException: (ArgumentError) Unsupported source. This method accepts String or IO
    at com.jrjackson.JrJacksonRaw.parse_str(com/jrjackson/JrJacksonRaw.java:95)
    at RUBY.load(/home/mindscratch/tomcat/webapps/myapp/WEB-INF/gems/gems/jrjackson-0.2.5/lib/jrjackson/jrjackson.rb:30)
    at RUBY.load(/home/mindscratch/tomcat/webapps/myapp/WEB-INF/gems/gems/multi_json-1.8.1/lib/multi_json/adapters/jr_jackson.rb:11)

After doing some debugging I found that the load method more or less expects a String. However, in my scenario it's getting a JRuby::RackInput object, hence the execption that is being raised.

I have a monkey patch in place that overrides the load method to do something horrible like this:

module JrJackson
  module Json
    class << self
      alias_method :original_jrjackson_load, :load

      def load(json_string, options = nil)
        class_name = json_string.class.name
        if class_name == "JRuby::RackInput"
          json_string = json_string.gets
          return JrJackson::Raw.parse_sym(json_string)
        else
          return original_jrjackson_json(json_string, options)
        end
      end
    end
  end
end

Optimization opportunities

Unable to spare time to actually hack these together, but here's a few suggestions.

  1. String.getBytes makes a copy. If possible, you can use String.getByteList and access the raw array from there to avoid allocation and copying (ByteList.getUnsafeBytes, getBegin, size).
  2. In JrJacksonRaw._parse, you can get an InputStream from an IO without as much overhead: ((RubyIO)arg).getInputStream(). It will allocate only an InputStream (maybe JRuby should cache it).
  3. You can use context.runtime rather than context.getRuntime() to avoid a tiny bit of method call overhead (may be nothing, may add up).
  4. Whenever possible, pass through ThreadContext to places you'll need it. getCurrentContext isn't slow, but it's several memory dereferences.
  5. I'm not positive, but I believe it's possible to get the raw stream bytes for a string out of the Jackson parser, rather than just using getText. That would avoid going from byte[] to String back to byte[] in JRuby, reducing Ruby String construction to three objects (RubyString, ByteList, byte[]) and a copy. Huge win if possible.

The key to performance is almost always going to be avoiding allocation, so use memory profiling tools to see where the top objects are, get rid of them, and repeat. The hprof JVM extension is useful for this (fair warning...it's REALLY REALLY slow...but you just want object counts from e.g. one iteration):

jruby -J-Xrunhprof:depth=20 ...

That will give you a listing of the top several hundred 20-deep allocation backtraces (unique backtraces that end in an object being created). From there you can see other paths to optimize.

Ping me any time :-)

Using BigDecimals for Floats

I'm trying to have the parser use BigDecimals instead of floats.

The flag DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS is respected in https://github.com/guyboertje/jrjackson/blob/master/src/main/java/com/jrjackson/RubyObjectDeserializer.java#L76, but there doesn't appear to be any way to set the flag.

For example, in https://github.com/guyboertje/jrjackson/blob/master/src/main/java/com/jrjackson/JrJacksonSym.java#L30, the instance of ObjectMapper is private, so I can't get access to it to do something like:
mapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);

Could a way of toggling this flag be exposed?

Add changelog

It'd be really helpful if there were a changelog listing what changed with each release and the release date. The README has a NEWS section, but it's hard to see the fully history that way.

Possible memory issue while serializing dates?

I'm having problems with a memory issue while using Logstash which I've tracked down to a large number of com.fasterxml.jackson.databind.modules.SimpleSerializers instances hanging around in memory.

I've grabbed object allocation reports and it looks like JrJackson is creating these objects in https://github.com/guyboertje/jrjackson/blob/master/src/main/java/com/jrjackson/RubyJacksonModule.java#L56 which has been called from https://github.com/guyboertje/jrjackson/blob/master/src/main/java/com/jrjackson/JrJacksonBase.java#L72. I've put the allocation call tree in a gist (https://gist.github.com/neilprosser/3298ada15ea5637a01bf) (apologies for the size) so you can see where the calls are coming from (from what I can see it's the JSON serialization for the Elasticsearch output and Redis output).

Looking at the code in JrJacksonBase.java (and assuming I don't have a custom date format, since I haven't explicitly set one anywhere, I'm just using Logstash but no date format mentioned in config or environment variables), does the code need to create a new provider every time if we're using the marker instance? Couldn't it cache that provider and use it if we're going to use RDF?

Hopefully you don't mind me creating the issue here. I figured since it's JSON serialization and it's come from two places it would be worth starting here and I can close this issue and shift it somewhere else if we find it shouldn't be here.

I've still got a broken instance running with a profiling agent available if you need more information. The symptoms I see are base memory usage (after old generation garbage collection) gradually increasing until Logstash spends all its time in garbage collection.

JRJackson throws RangeError when asked to dump Integer > Long.MAX_VALUE

When JrJackson::Base::generate(Object) is sent a payload containing a ruby Integer that is larger than (2^63)-1 (java's Long.MAX_VALUE), a RangeError is thrown:

╭─{ yaauie@castrovel:~/src/elastic/scratch/jrjackson-bigint-dump-fail }
╰─○ ruby -rjrjackson -e 'puts JrJackson::Base.generate({"b"=> 2**63})'
RangeError: bignum too big to convert into `long'
  generate at com/jrjackson/JrJacksonBase.java:70
    <main> at -e:1
ruby -rjrjackson -e 'puts JrJackson::Base.generate({"b"=> 2**63})'  6.51s user 0.31s system 304% cpu 2.238 total
[error: 1]
╭─{ yaauie@castrovel:~/src/elastic/scratch/jrjackson-bigint-dump-fail }
╰─○ ruby -rjrjackson -e 'puts JrJackson::Base.generate({"b"=> (2**63)-1})'
{"b":9223372036854775807}
ruby -rjrjackson -e 'puts JrJackson::Base.generate({"b"=> (2**63)-1})'  6.63s user 0.32s system 302% cpu 2.294 total
[success]

Platforms:

I have reproduced on current JRubies on both Java 8 and Java 11 on Darwin.

jruby 9.2.5.0 (2.5.0) 2018-12-06 6d5a228 Java HotSpot(TM) 64-Bit Server VM 25.152-b16 on 1.8.0_152-b16 +jit [darwin-x86_64]
jruby 9.2.5.0 (2.5.0) 2018-12-06 6d5a228 Java HotSpot(TM) 64-Bit Server VM 11.0.1+13-LTS on 11.0.1+13-LTS +jit [darwin-x86_64]

Does not work on JRuby 1.7.5

I'm using the latest available version which is 0.2.1

irb(main):001:0> require 'jrjackson'
LoadError: JRuby ext built for wrong Java version in `com.jrjackson.JrJacksonService': java.lang.UnsupportedClassVersionError: com/jrjackson/JrJacksonService : Unsupported major.minor version 51.0
        from org/jruby/RubyKernel.java:1082:in `require'
        from /Users/rwz/.rbenv/versions/jruby-1.7.5/lib/ruby/shared/rubygems/core_ext/kernel_require.rb:55:in `require'
        from /Users/rwz/.rbenv/versions/jruby-1.7.5/lib/ruby/gems/shared/gems/jrjackson-0.2.1/lib/jrjackson/jrjackson.rb:8:in `(root)'
        from org/jruby/RubyKernel.java:1082:in `require'
        from /Users/rwz/.rbenv/versions/jruby-1.7.5/lib/ruby/shared/rubygems/core_ext/kernel_require.rb:1:in `(root)'
        from /Users/rwz/.rbenv/versions/jruby-1.7.5/lib/ruby/shared/rubygems/core_ext/kernel_require.rb:55:in `require'
        from file:/Users/rwz/.rbenv/versions/jruby-1.7.5/lib/jruby.jar!/jruby/kernel19/kernel.rb:21:in `require_relative'
        from org/jruby/RubyKernel.java:1082:in `require'
        from /Users/rwz/.rbenv/versions/jruby-1.7.5/lib/ruby/gems/shared/gems/jrjackson-0.2.1/lib/jrjackson.rb:2:in `(root)'
        from /Users/rwz/.rbenv/versions/jruby-1.7.5/lib/ruby/shared/rubygems/core_ext/kernel_require.rb:1:in `(root)'
        from org/jruby/RubyKernel.java:1121:in `eval'
        from /Users/rwz/.rbenv/versions/jruby-1.7.5/lib/ruby/shared/rubygems/core_ext/kernel_require.rb:135:in `require'
        from (irb):1:in `evaluate'
        from org/jruby/RubyKernel.java:1517:in `loop'
        from org/jruby/RubyKernel.java:1282:in `catch'
        from org/jruby/RubyKernel.java:1282:in `catch'
        from /Users/rwz/.rbenv/versions/jruby-1.7.5/bin/irb:13:in `(root)'irb(main):002:0>

Awful decode performance

# coding: utf-8
require 'benchmark/ips'
require 'json'
require 'jrjackson'

obj = {
  :name => "Fredrick Smith",
  :quantity => 1_000_000,
  :addresses => {
    :address1 => "12 Heather Street, Parnell, Auckland, New Zealand",
    :address2 => "1 Queen Street, CBD, Auckland, New Zealand"
  }
}

json = JSON.dump(obj)

puts "Decode ====================="
Benchmark.ips do |x|
  x.config(time: 5, warmup: 10)

  x.report("JSON") { JSON.load(json) }
  x.report("JrJackson") { JrJackson::Json.load(json) }
  x.report("JrJackson Raw") { JrJackson::Raw.load(json, {}) }

  x.compare!
end

puts "Encode ====================="
Benchmark.ips do |x|
  x.config(time: 5, warmup: 10)

  x.report("JSON") { JSON.dump(obj) }
  x.report("JrJackson") { JrJackson::Json.dump(obj) }
  x.report("JrJackson Raw") { JrJackson::Raw.dump(obj) }

  x.compare!
end

# jruby-1.7.20.1
# jruby --server -J-Xmx2G -G -S serializer_benchmarks.rb
# Decode =====================
#                JSON:   193084.4 i/s
#       JrJackson Raw:    14945.7 i/s - 12.92x slower
#           JrJackson:    14388.0 i/s - 13.42x slower
#
# Encode =====================
#       JrJackson Raw:   391935.5 i/s
#           JrJackson:   388328.5 i/s - 1.01x slower
#                JSON:   357380.5 i/s - 1.10x slower

# jruby-9.0.1.0-pre150821
# jruby --server -J-Xmx2G -G -S serializer_benchmarks.rb
# Decode =====================
#                JSON:   166752.3 i/s
#       JrJackson Raw:    13582.2 i/s - 12.28x slower
#           JrJackson:    12453.7 i/s - 13.39x slower

# Encode =====================
#       JrJackson Raw:   361170.0 i/s
#           JrJackson:   321896.4 i/s - 1.12x slower
#                JSON:   300138.3 i/s - 1.20x slower

What am I doing wrong?

Naught gem breaks JrJackson when used as a value in a map

The Naught gem is unserializable in JrJackson. It cases crazy long stack traces. The only reason I'm reporting this is that the twitter ruby gem uses this craziness. If you try and encode the following:

JrJackson::Json.dump(Naught.build.new)
# => nil
 JrJackson::Json.dump({x: Naught.build.new})
# Raises exception below

The exception you get from the second example (in a map) is:

java.lang.ClassNotFoundException: com.fasterxml.jackson.module.afterburner.ser.BeanPropertyAccessor
    at java.lang.ClassLoader.findClass(ClassLoader.java:530)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
    at com.fasterxml.jackson.module.afterburner.util.MyClassLoader.loadAndResolve(MyClassLoader.java:86)
    at com.fasterxml.jackson.module.afterburner.ser.PropertyAccessorCollector.generateAccessorClass(PropertyAccessorCollector.java:166)
    at com.fasterxml.jackson.module.afterburner.ser.PropertyAccessorCollector.findAccessor(PropertyAccessorCollector.java:108)
    at com.fasterxml.jackson.module.afterburner.ser.SerializerModifier.changeProperties(SerializerModifier.java:55)
    at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.constructBeanSerializer(BeanSerializerFactory.java:351)
    at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanSerializer(BeanSerializerFactory.java:263)
    at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:222)
    at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:152)
    at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1108)
    at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1068)
    at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:476)
    at com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap.findAndAddSecondarySerializer(PropertySerializerMap.java:95)
    at com.fasterxml.jackson.databind.ser.std.MapSerializer._findAndAddDynamic(MapSerializer.java:689)
    at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:486)
    at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:412)
    at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:27)
    at com.jrjackson.RubyAnySerializer.serialize(RubyAnySerializer.java:93)
    at com.jrjackson.RubyAnySerializer.serialize(RubyAnySerializer.java:17)
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:128)
    at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:2881)
    at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:2338)
    at com.jrjackson.JrJacksonRaw.generate(JrJacksonRaw.java:144)
    at com.jrjackson.JrJacksonRaw$INVOKER$s$0$1$generate.call(JrJacksonRaw$INVOKER$s$0$1$generate.gen)
    at org.jruby.internal.runtime.methods.JavaMethod$JavaMethodN.call(JavaMethod.java:673)
    at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:214)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:202)
    at org.jruby.ast.CallTwoArgNode.interpret(CallTwoArgNode.java:59)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.WhenOneArgNode.whenSlowTest(WhenOneArgNode.java:36)
    at org.jruby.ast.WhenOneArgNode.when(WhenOneArgNode.java:46)
    at org.jruby.ast.CaseNode.interpret(CaseNode.java:133)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
    at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.RootNode.interpret(RootNode.java:129)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_EVAL(ASTInterpreter.java:95)
    at org.jruby.evaluator.ASTInterpreter.evalWithBinding(ASTInterpreter.java:184)
    at org.jruby.RubyKernel.evalCommon(RubyKernel.java:1148)
    at org.jruby.RubyKernel.eval(RubyKernel.java:1106)
    at org.jruby.RubyBinding.eval(RubyBinding.java:134)
    at org.jruby.RubyBinding$INVOKER$i$0$2$eval.call(RubyBinding$INVOKER$i$0$2$eval.gen)
    at org.jruby.internal.runtime.methods.JavaMethod$JavaMethodN.call(JavaMethod.java:677)
    at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:222)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:236)
    at org.jruby.ast.CallThreeArgNode.interpret(CallThreeArgNode.java:61)
    at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.EnsureNode.interpret(EnsureNode.java:96)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:168)
    at org.jruby.ast.FCallOneArgNode.interpret(FCallOneArgNode.java:36)
    at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.RescueNode.executeBody(RescueNode.java:221)
    at org.jruby.ast.RescueNode.interpret(RescueNode.java:116)
    at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.IfNode.interpret(IfNode.java:116)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:225)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:219)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:202)
    at org.jruby.ast.FCallTwoArgNode.interpret(FCallTwoArgNode.java:38)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
    at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:157)
    at org.jruby.runtime.Block.yield(Block.java:142)
    at org.jruby.RubyContinuation.enter(RubyContinuation.java:107)
    at org.jruby.RubyKernel.rbCatch19Common(RubyKernel.java:1281)
    at org.jruby.RubyKernel.rbCatch19(RubyKernel.java:1274)
    at org.jruby.RubyKernel$INVOKER$s$rbCatch19.call(RubyKernel$INVOKER$s$rbCatch19.gen)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:177)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:188)
    at org.jruby.ast.FCallOneArgBlockNode.interpret(FCallOneArgBlockNode.java:34)
    at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
    at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:157)
    at org.jruby.runtime.Block.yield(Block.java:142)
    at org.jruby.RubyContinuation.enter(RubyContinuation.java:107)
    at org.jruby.RubyKernel.rbCatch19Common(RubyKernel.java:1281)
    at org.jruby.RubyKernel.rbCatch19(RubyKernel.java:1274)
    at org.jruby.RubyKernel$INVOKER$s$rbCatch19.call(RubyKernel$INVOKER$s$rbCatch19.gen)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:177)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:188)
    at org.jruby.ast.FCallOneArgBlockNode.interpret(FCallOneArgBlockNode.java:34)
    at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:168)
    at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
    at org.jruby.ast.IfNode.interpret(IfNode.java:110)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.CaseNode.interpret(CaseNode.java:138)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
    at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:157)
    at org.jruby.runtime.Interpreted19Block.yieldSpecific(Interpreted19Block.java:130)
    at org.jruby.runtime.Block.yieldSpecific(Block.java:111)
    at org.jruby.RubyKernel.loop(RubyKernel.java:1511)
    at org.jruby.RubyKernel$INVOKER$s$0$0$loop.call(RubyKernel$INVOKER$s$0$0$loop.gen)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:316)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:145)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:154)
    at org.jruby.ast.FCallNoArgBlockNode.interpret(FCallNoArgBlockNode.java:32)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:139)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:187)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:306)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:136)
    at org.jruby.ast.VCallNode.interpret(VCallNode.java:88)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
    at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:194)
    at org.jruby.runtime.Interpreted19Block.call(Interpreted19Block.java:125)
    at org.jruby.runtime.Block.call(Block.java:101)
    at org.jruby.RubyProc.call(RubyProc.java:290)
    at org.jruby.RubyProc.call19(RubyProc.java:271)
    at org.jruby.RubyProc$INVOKER$i$0$0$call19.call(RubyProc$INVOKER$i$0$0$call19.gen)
    at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:202)
    at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:198)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:306)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:136)
    at org.jruby.ast.CallNoArgNode.interpret(CallNoArgNode.java:60)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.EnsureNode.interpret(EnsureNode.java:96)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:161)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:195)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:316)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:145)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:149)
    at org.jruby.ast.FCallNoArgBlockPassNode.interpret(FCallNoArgBlockPassNode.java:27)
    at org.jruby.ast.IfNode.interpret(IfNode.java:118)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:161)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:195)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:316)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:145)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:154)
    at org.jruby.ast.CallNoArgBlockNode.interpret(CallNoArgBlockNode.java:64)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.EnsureNode.interpret(EnsureNode.java:96)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:139)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:187)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:306)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:136)
    at org.jruby.ast.CallNoArgNode.interpret(CallNoArgNode.java:60)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
    at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.RescueNode.executeBody(RescueNode.java:221)
    at org.jruby.ast.RescueNode.interpret(RescueNode.java:116)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:225)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:219)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:346)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:204)
    at org.jruby.ast.CallTwoArgNode.interpret(CallTwoArgNode.java:59)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.IfNode.interpret(IfNode.java:116)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:139)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:187)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:306)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:136)
    at org.jruby.ast.CallNoArgNode.interpret(CallNoArgNode.java:60)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
    at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:194)
    at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:177)
    at org.jruby.runtime.Block.yieldNonArray(Block.java:153)
    at org.jruby.RubyBasicObject.yieldUnder(RubyBasicObject.java:1589)
    at org.jruby.RubyBasicObject.instance_exec19(RubyBasicObject.java:1566)
    at org.jruby.RubyBasicObject$INVOKER$i$0$3$instance_exec19.call(RubyBasicObject$INVOKER$i$0$3$instance_exec19.gen)
    at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:210)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:336)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:179)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:183)
    at org.jruby.ast.CallOneArgBlockPassNode.interpret(CallOneArgBlockPassNode.java:60)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.RescueNode.executeBody(RescueNode.java:221)
    at org.jruby.ast.RescueNode.interpret(RescueNode.java:116)
    at org.jruby.ast.EnsureNode.interpret(EnsureNode.java:96)
    at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
    at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:157)
    at org.jruby.runtime.Interpreted19Block.yieldSpecific(Interpreted19Block.java:130)
    at org.jruby.runtime.Block.yieldSpecific(Block.java:111)
    at org.jruby.ast.ZYieldNode.interpret(ZYieldNode.java:25)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.IfNode.interpret(IfNode.java:116)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.RescueNode.executeBody(RescueNode.java:221)
    at org.jruby.ast.RescueNode.interpret(RescueNode.java:116)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:161)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:195)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:316)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:145)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:154)
    at org.jruby.ast.FCallNoArgBlockNode.interpret(FCallNoArgBlockNode.java:32)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.IfNode.interpret(IfNode.java:116)
    at org.jruby.ast.IfNode.interpret(IfNode.java:118)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.RescueNode.executeBody(RescueNode.java:221)
    at org.jruby.ast.RescueNode.interpret(RescueNode.java:116)
    at org.jruby.ast.EnsureNode.interpret(EnsureNode.java:96)
    at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.EnsureNode.interpret(EnsureNode.java:96)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:225)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:219)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:346)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:204)
    at org.jruby.ast.CallTwoArgNode.interpret(CallTwoArgNode.java:59)
    at org.jruby.ast.DAsgnNode.interpret(DAsgnNode.java:110)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
    at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:157)
    at org.jruby.runtime.Block.yield(Block.java:142)
    at org.jruby.RubyArray.collect(RubyArray.java:2399)
    at org.jruby.RubyArray.map19(RubyArray.java:2412)
    at org.jruby.RubyArray$INVOKER$i$0$0$map19.call(RubyArray$INVOKER$i$0$0$map19.gen)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:143)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:154)
    at org.jruby.ast.CallNoArgBlockNode.interpret(CallNoArgBlockNode.java:64)
    at org.jruby.ast.CallNoArgNode.interpret(CallNoArgNode.java:60)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
    at org.jruby.ast.FCallOneArgNode.interpret(FCallOneArgNode.java:36)
    at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.RescueNode.executeBody(RescueNode.java:221)
    at org.jruby.ast.RescueNode.interpret(RescueNode.java:116)
    at org.jruby.ast.EnsureNode.interpret(EnsureNode.java:96)
    at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
    at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
    at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:157)
    at org.jruby.runtime.Block.yield(Block.java:142)
    at org.jruby.RubyArray.collect(RubyArray.java:2399)
    at org.jruby.RubyArray.map19(RubyArray.java:2412)
    at org.jruby.RubyArray$INVOKER$i$0$0$map19.call(RubyArray$INVOKER$i$0$0$map19.gen)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:316)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:145)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:154)
    at org.jruby.ast.CallNoArgBlockNode.interpret(CallNoArgBlockNode.java:64)
    at org.jruby.ast.CallNoArgNode.interpret(CallNoArgNode.java:60)
    at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.RescueNode.executeBody(RescueNode.java:221)
    at org.jruby.ast.RescueNode.interpret(RescueNode.java:116)
    at org.jruby.ast.EnsureNode.interpret(EnsureNode.java:96)
    at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
    at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
    at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:157)
    at org.jruby.runtime.Block.yield(Block.java:142)
    at org.jruby.RubyArray.collect(RubyArray.java:2399)
    at org.jruby.RubyArray.map19(RubyArray.java:2412)
    at org.jruby.RubyArray$INVOKER$i$0$0$map19.call(RubyArray$INVOKER$i$0$0$map19.gen)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:316)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:145)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:154)
    at org.jruby.ast.CallNoArgBlockNode.interpret(CallNoArgBlockNode.java:64)
    at org.jruby.ast.CallNoArgNode.interpret(CallNoArgNode.java:60)
    at org.jruby.ast.IfNode.interpret(IfNode.java:110)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.EnsureNode.interpret(EnsureNode.java:96)
    at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
    at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
    at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:157)
    at org.jruby.runtime.Interpreted19Block.yieldSpecific(Interpreted19Block.java:135)
    at org.jruby.runtime.Block.yieldSpecific(Block.java:120)
    at org.jruby.ast.YieldOneNode.interpret(YieldOneNode.java:35)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.EnsureNode.interpret(EnsureNode.java:96)
    at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:204)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:211)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:336)
    at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:179)
    at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:188)
    at org.jruby.ast.CallOneArgBlockNode.interpret(CallOneArgBlockNode.java:60)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
    at org.jruby.ast.FCallOneArgNode.interpret(FCallOneArgNode.java:36)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:225)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:219)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:346)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:204)
    at org.jruby.ast.CallTwoArgNode.interpret(CallTwoArgNode.java:59)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.IfNode.interpret(IfNode.java:118)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:268)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:235)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:366)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:238)
    at org.jruby.ast.FCallThreeArgNode.interpret(FCallThreeArgNode.java:40)
    at org.jruby.ast.CallNoArgNode.interpret(CallNoArgNode.java:60)
    at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
    at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:139)
    at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:187)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:306)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:136)
    at org.jruby.ast.CallNoArgNode.interpret(CallNoArgNode.java:60)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
    at org.jruby.ast.RootNode.interpret(RootNode.java:129)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_ROOT(ASTInterpreter.java:121)
    at org.jruby.Ruby.runInterpreter(Ruby.java:894)
    at org.jruby.Ruby.loadFile(Ruby.java:2860)
    at org.jruby.runtime.load.LibrarySearcher$ResourceLibrary.loadScript(LibrarySearcher.java:264)
    at org.jruby.runtime.load.LibrarySearcher$ResourceLibrary.load(LibrarySearcher.java:252)
    at org.jruby.runtime.load.LibrarySearcher$FoundLibrary.load(LibrarySearcher.java:51)
    at org.jruby.runtime.load.LoadService.load(LoadService.java:358)
    at org.jruby.RubyKernel.loadCommon(RubyKernel.java:1099)
    at org.jruby.RubyKernel.load19(RubyKernel.java:1091)
    at org.jruby.RubyKernel$INVOKER$s$0$1$load19.call(RubyKernel$INVOKER$s$0$1$load19.gen)
    at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:210)
    at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:206)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
    at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
    at Users.andrewvc.$_dot_rbenv.versions.jruby_minus_1_dot_7_dot_20.bin.rspec.__file__(/Users/andrewvc/.rbenv/versions/jruby-1.7.20/bin/rspec:23)
    at Users.andrewvc.$_dot_rbenv.versions.jruby_minus_1_dot_7_dot_20.bin.rspec.load(/Users/andrewvc/.rbenv/versions/jruby-1.7.20/bin/rspec)
    at org.jruby.Ruby.runScript(Ruby.java:867)
    at org.jruby.Ruby.runScript(Ruby.java:860)
    at org.jruby.Ruby.runNormally(Ruby.java:729)
    at org.jruby.Ruby.runFromMain(Ruby.java:578)
    at org.jruby.Main.doRunFromMain(Main.java:395)
    at org.jruby.Main.internalRun(Main.java:290)
    at org.jruby.Main.run(Main.java:217)
    at org.jruby.Main.main(Main.java:197)
JrJackson::ParseError: Failed to load class 'org.jruby.RubyBasicObject$Access4JacksonSerializer': com.fasterxml.jackson.module.afterburner.ser.BeanPropertyAccessor
from com/jrjackson/JrJacksonRaw.java:147:in `generate'

Add streaming deserialization

Open an IO object, pass it, options and a callable into JrJackson::Json.load, write string chunks to the IO, jrjackson the callable is called with a deserialized object each time one is found. Deserialization ends when the stream is closed.

Various MultiJson Errors

Hi! I'm the author of the stretcher rubygem, which uses multi json. I believe some errors reported there may have a root cause in this gem. Are these issues with your gem or multi json? The GSON gem works fine.

stretcher/stretcher#43

concurrency concern in RubyJacksonModule.createProvider

Multithreaded serialization of JSON will suffer from contention in RubyJacksonModule.createProvider due to calling java.util.TimeZone.getTimeZone which is synchronized. This happens here: https://github.com/guyboertje/jrjackson/blob/master/src/main/java/com/jrjackson/RubyJacksonModule.java#L58

To observe this locking do:

ruby -rjrjackson -e "now = Time.now; threads = 100.times.map {|i| Thread.new { loop { JrJackson::Json.dump(\"a\" => 1) } } }; threads.each(&:join)" 

getting jstack on this process shows many occurrences of the following stack:

jstack 42939 | grep BLOCKED -A 4 -B 1  
"Ruby-0-Thread-99: -e:1" #114 daemon prio=5 os_prio=31 cpu=3003.00ms elapsed=43.85s tid=0x00007ff2cf81f000 nid=0x17d03 waiting for monitor entry  [0x000070001c58b000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at java.util.TimeZone.getTimeZone([email protected]/TimeZone.java:517)
	- waiting to lock <0x0000000700b0c4c0> (a java.lang.Class for java.util.TimeZone)
	at com.jrjackson.RubyJacksonModule.createProvider(RubyJacksonModule.java:58)
	at com.jrjackson.JrJacksonBase.generate(JrJacksonBase.java:66)
--

Almost all 100 threads become blocked:

% jstack 42939 | grep BLOCKED  | wc -l
      94
% jstack 42939 | grep BLOCKED  | wc -l
      98

v0.4.1 is broken - missing jar

lib/jrjackson/jrjackson.rb points to "jars/jrjackson-1.2.19.jar" which has been replaced with "jars/jrjackson-1.2.20.jar".

Hash dump with DateTime produces SystemStackError

Version: jruby-1.7.19

> JrJackson::Json.dump({:datetime => DateTime.parse("2014-01-27T18:24:46+01:00")})
SystemStackError: stack level too deep
    from org/jruby/RubyKernel.java:1107:in `eval'
    from org/jruby/RubyKernel.java:1507:in `loop'
    from org/jruby/RubyKernel.java:1270:in `catch'
    from org/jruby/RubyKernel.java:1270:in `catch'
    from script/console:7:in `(root)'

ArrayIndexOutOfBoundsException when calling `json.dump` concurrently with date/time

Running json.dump concurrently across multiple threads can cause an ArrayIndexOutOfBoundsException:

warning: thread "Ruby-0-Thread-53: jrjack.rb:1" terminated with exception (report_on_exception is true):
java.lang.ArrayIndexOutOfBoundsException: 965
	at sun.util.calendar.BaseCalendar.getCalendarDateFromFixedDate(BaseCalendar.java:453)
	at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2397)
	at java.util.GregorianCalendar.computeFields(GregorianCalendar.java:2312)
	at java.util.Calendar.setTimeInMillis(Calendar.java:1804)
	at java.util.Calendar.setTime(Calendar.java:1770)
	at java.text.SimpleDateFormat.format(SimpleDateFormat.java:943)
	at java.text.SimpleDateFormat.format(SimpleDateFormat.java:936)
	at java.text.DateFormat.format(DateFormat.java:345)
	at com.jrjackson.RubyAnySerializer.serializeTime(RubyAnySerializer.java:244)
	at com.jrjackson.RubyAnySerializer.serialize(RubyAnySerializer.java:196)
	at com.jrjackson.RubyAnySerializer.serializeHash(RubyAnySerializer.java:226)
	at com.jrjackson.RubyAnySerializer.serialize(RubyAnySerializer.java:162)
	at com.jrjackson.JrJacksonBase.generate(JrJacksonBase.java:73)

Snipped of code that reproduces the issue (courtesy of @jsvd)

require 'jrjackson'                                                                                                         

Thread.abort_on_exception = true

now = Time.now

# we need multi threading to trigger this issue
num_threads = 100 

threads = num_threads.times.map do |i| 
  Thread.new do
    # this is OK: 
    #   loop { JrJackson::Json.dump(now) }
    # but this causes exception:
    loop { JrJackson::Json.dump("a" => now) }
  end 
end
threads.each(&:join)

Unexpected result when serialising TimeZones in a hashmap

I'm seeing unexpected behaviour when serialising an ActiveSupport::TimeWithZone i a hashmap.

It works as expected when dumping the time object directly.

JrJackson::Json.dump Time.zone.now
=> "\"2014-05-08T22:04:56Z\""

JrJackson::Json.dump t: Time.zone.now
=> "{\"t\":[58,4,22,8,5,2014,4,128,false,\"UTC\"]}"

JrJackson::Json.dump t: Time.now
=> "{\"t\":\"2014-05-08 23:05:03 BST\"}"

JrJackson freaks out when used inside TorqueBox

TorqueBox creates multiple Ruby runtimes, and JrJackson uses Ruby.getGlobalRuntime() in a few places, for example here, here, and here. This causes objects to bleed over into runtimes in which they weren't created, which causes very strange failures. According to @bbrowning, calling Ruby.getGlobalRuntime() should be avoided for this very reason.

JrJackson does seem to get this right in some places, for example here.

Issue with JrJackson::Json.generate

Using JRuby 1.6.7 in 1.9 mode, Oracle Java 6, Mac OSX Lion.

If I create a simple object, like this:

class Foo
  attr_access :bar, :baz
  def initialize(bar = "bar", baz = "baz")
    @bar, @baz = bar, baz
  end
end

...and try to pass it through JrJackson::Json.generate:

f = Foo.new
JrJackson::Json.generate f

...I get the following error and stack trace:

NativeException - org.codehaus.jackson.map.JsonMappingException: Conflicting getter definitions for property "verbose": org.jruby.Ruby#getVerbose(0 params) vs org.jruby.Ruby#isVerbose(0 params) (through reference chain: org.jruby.RubyObject["runtime"]):
    org/codehaus/jackson/map/ser/StdSerializerProvider.java:740:in `_createAndCacheUntypedSerializer'
    org/codehaus/jackson/map/ser/StdSerializerProvider.java:344:in `findValueSerializer'
    org/codehaus/jackson/map/ser/impl/PropertySerializerMap.java:39:in `findAndAddSerializer'
    org/codehaus/jackson/map/ser/BeanPropertyWriter.java:463:in `_findAndAddDynamic'
    org/codehaus/jackson/map/ser/BeanPropertyWriter.java:441:in `serializeAsField'
    org/codehaus/jackson/map/ser/std/BeanSerializerBase.java:150:in `serializeFields'
    org/codehaus/jackson/map/ser/BeanSerializer.java:112:in `serialize'
    org/codehaus/jackson/map/ser/StdSerializerProvider.java:610:in `_serializeValue'
    org/codehaus/jackson/map/ser/StdSerializerProvider.java:256:in `serializeValue'
    org/codehaus/jackson/map/ObjectMapper.java:2575:in `_configAndWriteValue'
    org/codehaus/jackson/map/ObjectMapper.java:2097:in `writeValueAsString'
    /Users/semperos/.rbenv/versions/jruby-1.6.7/lib/ruby/gems/1.8/gems/jrjackson-0.0.7/lib/jrjackson/jrjackson.rb:18:in `generate'

Everything works fine for a regular Hash in my setup. Thoughts?

JrJackson::ParseError: Failed to load class 'org.jruby.RubyObject$Access4JacksonDeserializer45931591'

I'm experiencing a JrJackson::ParseError when attempting to serialise a previously deserialised Hash to JSON again where the Hash had a new entry added containing an arbitrary Ruby object.

It seems related to Java types. The original parse from JSON was with JrJackson::Java to allow Java objects that quack like Ruby objects to be returned. This results in a Java::Util::HashMap. However, when an arbitrary Ruby object is then added to that hash, and serialisation is attempted again, the JrJackson::ParseError occurs.

No error occurs if the original parse from JSON was with JrJackson::Ruby

Minimal reproduction case, with only JrJackson: https://gist.github.com/driskell/d11a988958b0185cf982
Download files and run: bundle install --no-deployment --path vendor; bundle exec jruby test.rb
Tested with JRuby 1.7.6.
JrJackson version 0.3.6.

$ rvm use jruby
Using /Users/Jason/.rvm/gems/jruby-1.7.16
$ bundle exec jruby test.rb
JrJackson::ParseError: Failed to load class 'org.jruby.RubyObject$Access4JacksonDeserializer45931591': com.fasterxml.jackson.module.afterburner.ser.BeanPropertyAccessor
  generate at com/jrjackson/JrJacksonBase.java:83
    (root) at test.rb:14

From: logstash-plugins/logstash-output-elasticsearch#294
From: driskell/log-courier#247

DateTime serialization raises an exception

Hi,

I'm using jr_jackson to serialize data from Sequel::Datasets. The db driver uses DateTime for time representation.

When calling JrJackson::Json.dump (with no extra arguments) on the newly-obtained data set in Hash format, I'm getting an exception:

JrJackson::ParseError: Cannot find Serializer for class: org.jruby.RubyObject

...Probably because DateTime can't be converted to string by JrJacksonRaw.generate. My data is quite simple: just a Hash with strings and a couple of dates.

I've attached a simple test that reproduces this behavior:

 def test_can_load_datetime
    expected = '{"datetime": "2014-01-27T18:24:46+01:00"}'
    hash = {:datetime => DateTime.parse("2014-01-27T18:24:46+01:00")}
    actual = JrJackson::Json.dump(hash)
    assert_equal expected, actual
  end
coruscant:test nando$ jruby jrjackson_test.rb 
Run options: 

# Running tests:

.E......

Finished tests in 0.719000s, 11.1266 tests/s, 25.0348 assertions/s.

  1) Error:
test_can_load_datetime(JrJacksonTest):
JrJackson::ParseError: Cannot find Serializer for class: org.jruby.RubyObject
    com/jrjackson/JrJacksonRaw.java:133:in `generate'
    /Users/nando/d/playground/jrjackson/lib/jrjackson/jrjackson.rb:37:in `dump'
    jrjackson_test.rb:144:in `test_can_load_datetime'
    org/jruby/RubyBasicObject.java:1659:in `__send__'

8 tests, 18 assertions, 0 failures, 1 errors, 0 skips
coruscant:test nando$ 

Am I missing something? Many thanks!

Regards,
//nando

Incorrect dump of Date when in a nested structure

 $ jirb
 :001 > require 'date'
 => true
 :002 > require 'jrjackson'
 => true
 :003 > JrJackson::Json.dump(Date.today)
 => "2016-01-11"
 :004 > JrJackson::Json.dump([Date.today])
 => "[\"2016-01-11 00:00:00 +0100\"]"

The above session uses JrJackson 0.3.8 and JRuby 1.7.21. I am aware of #29 and https://github.com/guyboertje/jrjackson/wiki/Ruby-Time-serialisation however this concerns only dates. As far as I know dates should be TZ unaware, so the generation of a date should always result in a string of the "YYYY-MM-DD" format.

Integers dumping as strings instead of numbers

Reproducing in jirb, using JrJackson version 0.4.6:

> require 'jrjackson'   # => true
> JrJackson::Json.dump({ foo: 7 })    # => "{\"foo\":\"7\"}"

I would have expected the value 7 to be serialized as a number rather than a string. This is crucial to some of my use cases, which fail schema validation when numbers are given as strings.

I've discovered a kludgy workaround, which is to include JRuby's own json library from stdlib:

> require 'jrjackson'    # => true
> JrJackson::Json.dump({ foo: 7 })   # => "{\"foo\":\"7\"}"
> require 'json'   #  => true
> JrJackson::Json.dump({ foo: 7 })    # => "{\"foo\":7}"

I'm assuming this works because including the library attaches #to_json methods to every basic class. Relying on it seems inconsistent and bloatish, however. I would rather use only one JSON library in my code, and I would rather it be JrJackson for the speed. I'm not deep enough in Java to figure out the best place to patch the gem, but will take a shot at it after my own work is completed if nobody else does.

`use_bigdecimal` default is `true`

README "Will return BigDecimal objects instead of Float If used with the :raw option",
but use_bigdecimal default is true in java source. it confuses me.

JrJackson::Json.load check for date string regex

Why does JrJackson::Json.load checks for an invalid json date pattern string to transform it back as a valid json string? in https://github.com/guyboertje/jrjackson/blob/master/lib/jrjackson/jrjackson.rb#L17

regex check can be an expensive, especially in the context of high frequency json message processing. Not sure why this is done but maybe make that check configurable? Of course we can always bypass this and call JrJackson::Raw.parse_raw directly too...

Let me know what you think and I'll create a PR depending.

IllegalArgumentException: No enum constant com.jrjackson.RubyAnySerializer.RUBYCLASS.LogStash::Timestamp

While profiling Logstash, I noticed that a lot of time (5-10% of time is spent) in the IllegalArgumentException.fillInStackTrace method.
I analyzed why so many IllegalArgumentException were thrown: here is the stack trace:

java.lang.IllegalArgumentException: No enum constant com.jrjackson.RubyAnySerializer.RUBYCLASS.LogStash::Timestamp
        at java.lang.Enum.valueOf(Enum.java:238)
        at com.jrjackson.RubyAnySerializer$RUBYCLASS.valueOf(RubyAnySerializer.java:30)
        at com.jrjackson.RubyAnySerializer.serialize(RubyAnySerializer.java:131)
        at com.jrjackson.RubyAnySerializer.serializeHash(RubyAnySerializer.java:205)
        at com.jrjackson.RubyAnySerializer.serialize(RubyAnySerializer.java:139)
        at com.jrjackson.JrJacksonBase.generate(JrJacksonBase.java:70)
        at com.jrjackson.JrJacksonBase$INVOKER$s$0$1$generate.call(JrJacksonBase$INVOKER$s$0$1$generate.gen)
        at org.jruby.internal.runtime.methods.JavaMethod$JavaMethodN.call(JavaMethod.java:671)
        at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:214)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:202)
        at org.jruby.ast.CallTwoArgNode.interpret(CallTwoArgNode.java:59)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.WhenOneArgNode.whenSlowTest(WhenOneArgNode.java:36)
        at org.jruby.ast.WhenOneArgNode.when(WhenOneArgNode.java:46)
        at org.jruby.ast.CaseNode.interpret(CaseNode.java:133)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:225)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:219)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:202)
        at org.jruby.ast.CallTwoArgNode.interpret(CallTwoArgNode.java:59)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:225)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:219)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:202)
        at org.jruby.ast.CallTwoArgNode.interpret(CallTwoArgNode.java:59)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:225)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:219)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:202)
        at org.jruby.ast.CallTwoArgNode.interpret(CallTwoArgNode.java:59)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:168)
        at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
        at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
        at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:157)
        at org.jruby.runtime.Block.yield(Block.java:142)
        at org.jruby.RubyArray.collect(RubyArray.java:2400)
        at org.jruby.RubyArray.map19(RubyArray.java:2414)
        at org.jruby.RubyArray$INVOKER$i$0$0$map19.call(RubyArray$INVOKER$i$0$0$map19.gen)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:316)
        at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:145)
        at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:154)
        at org.jruby.ast.CallNoArgBlockNode.interpret(CallNoArgBlockNode.java:64)
        at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
        at org.jruby.ast.WhenOneArgNode.whenNoTest(WhenOneArgNode.java:27)
        at org.jruby.ast.WhenOneArgNode.when(WhenOneArgNode.java:45)
        at org.jruby.ast.CaseNode.interpret(CaseNode.java:133)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
        at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
        at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.IfNode.interpret(IfNode.java:116)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
        at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
        at org.jruby.ast.FCallOneArgNode.interpret(FCallOneArgNode.java:36)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
        at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
        at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:157)
        at org.jruby.runtime.Block.yield(Block.java:142)
        at org.jruby.ext.thread.Mutex.synchronize(Mutex.java:149)
        at org.jruby.ext.thread.Mutex$INVOKER$i$0$0$synchronize.call(Mutex$INVOKER$i$0$0$synchronize.gen)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:316)
        at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:145)
        at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:154)
        at org.jruby.ast.CallNoArgBlockNode.interpret(CallNoArgBlockNode.java:64)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
        at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.RescueNode.executeBody(RescueNode.java:221)
        at org.jruby.ast.RescueNode.interpret(RescueNode.java:116)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:225)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:219)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:346)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:204)
        at org.jruby.ast.FCallTwoArgNode.interpret(FCallTwoArgNode.java:38)
        at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
        at org.jruby.ast.FCallOneArgNode.interpret(FCallOneArgNode.java:36)
        at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNode.java:123)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.RescueNode.executeBody(RescueNode.java:221)
        at org.jruby.ast.RescueNode.interpret(RescueNode.java:116)
        at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
        at org.jruby.ast.WhileNode.interpret(WhileNode.java:131)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
        at org.jruby.ast.FCallOneArgNode.interpret(FCallOneArgNode.java:36)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
        at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
        at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:157)
        at org.jruby.runtime.Block.yield(Block.java:142)
        at org.jruby.RubyArray.eachSlice(RubyArray.java:1643)
        at org.jruby.RubyArray.each_slice(RubyArray.java:1653)
        at org.jruby.RubyArray$INVOKER$i$1$0$each_slice.call(RubyArray$INVOKER$i$1$0$each_slice.gen)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:336)
        at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:179)
        at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:188)
        at org.jruby.ast.CallOneArgBlockNode.interpret(CallOneArgBlockNode.java:60)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
        at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.EnsureNode.interpret(EnsureNode.java:96)
        at org.jruby.ast.BeginNode.interpret(BeginNode.java:83)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
        at org.jruby.ast.FCallOneArgNode.interpret(FCallOneArgNode.java:36)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
        at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
        at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:194)
        at org.jruby.runtime.Interpreted19Block.call(Interpreted19Block.java:125)
        at org.jruby.runtime.Block.call(Block.java:101)
        at org.jruby.RubyProc.call(RubyProc.java:300)
        at org.jruby.internal.runtime.methods.ProcMethod.call(ProcMethod.java:64)
        at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:210)
        at org.jruby.internal.runtime.methods.DynamicMethod.call(DynamicMethod.java:206)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
        at org.jruby.ast.CallOneArgNode.interpret(CallOneArgNode.java:57)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
        at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
        at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:157)
        at org.jruby.runtime.Block.yield(Block.java:142)
        at org.jruby.RubyHash$13.visit(RubyHash.java:1355)
        at org.jruby.RubyHash.visitLimited(RubyHash.java:648)
        at org.jruby.RubyHash.visitAll(RubyHash.java:634)
        at org.jruby.RubyHash.iteratorVisitAll(RubyHash.java:1306)
        at org.jruby.RubyHash.each_pairCommon(RubyHash.java:1351)
        at org.jruby.RubyHash.each19(RubyHash.java:1342)
        at org.jruby.RubyHash$INVOKER$i$0$0$each19.call(RubyHash$INVOKER$i$0$0$each19.gen)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:316)
        at org.jruby.runtime.callsite.CachingCallSite.callBlock(CachingCallSite.java:145)
        at org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:154)
        at org.jruby.ast.CallNoArgBlockNode.interpret(CallNoArgBlockNode.java:64)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:182)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:203)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:326)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
        at org.jruby.ast.FCallOneArgNode.interpret(FCallOneArgNode.java:36)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
        at org.jruby.ast.WhileNode.interpret(WhileNode.java:131)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHOD(ASTInterpreter.java:74)
        at org.jruby.internal.runtime.methods.InterpretedMethod.call(InterpretedMethod.java:225)
        at org.jruby.internal.runtime.methods.DefaultMethod.call(DefaultMethod.java:219)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:346)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:204)
        at org.jruby.ast.FCallTwoArgNode.interpret(FCallTwoArgNode.java:38)
        at org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
        at org.jruby.ast.BlockNode.interpret(BlockNode.java:71)
        at org.jruby.evaluator.ASTInterpreter.INTERPRET_BLOCK(ASTInterpreter.java:112)
        at org.jruby.runtime.Interpreted19Block.evalBlockBody(Interpreted19Block.java:206)
        at org.jruby.runtime.Interpreted19Block.yield(Interpreted19Block.java:194)
        at org.jruby.runtime.Interpreted19Block.call(Interpreted19Block.java:125)
        at org.jruby.runtime.Block.call(Block.java:101)
        at org.jruby.RubyProc.call(RubyProc.java:300)
        at org.jruby.RubyProc.call(RubyProc.java:230)
        at org.jruby.internal.runtime.RubyRunnable.run(RubyRunnable.java:99)
        at java.lang.Thread.run(Thread.java:745)

As you can see the stack trace is pretty long, this may explain why the fillInStackTrace takes so many time.

Adding a simple check (like rubyClassName contains :: or rubyClassName matches [A-Za-Z]+) to skip the RUBYCLASS.valueOf:

            try {
                clazz = RUBYCLASS.valueOf(rubyClassName);
            } catch (IllegalArgumentException e) {
                serializeUnknownRubyObject(value.getRuntime().getCurrentContext(), value, jgen, provider);
                return;
           }

Ownership transfer of JrJackson to Elastic/Logstash org

As I have retired from software development work and am fully occupied with other things, it is time to transfer ownership of this project to the biggest users of it i.e. Elastic/Logstash.

I have sent an invite to @jsvd to be a collaborator and invited the elastic rubygems user as an owner of the rubygems entry.

Joao will action the transfer on github and complete the invite email from the rubygems server.

Lokking at the Rev deps on rubygems there are two projects that use jrjackson with recently published gems (<3 months), it would be good etiquette to inform the project owners of this change (they may or may not see this issue)

Hugs,
Guy

Ruby parse() null/nil handling

Per elastic/logstash/issues/8439 the JrJackson::Ruby.parse returns a Java null upon parsing an empty string.

This null return seems to confuse the JRuby JIT some very specific cases. I was able to reproduce the problem with a simple script as per the example in elastic/logstash/issues/8439 copied here:

Tested using JrJackson 0.4.3 and JRuby 9.1.13.0 (also tried with JrJackson 0.4.2, JRuby 9.1.12.0 and 1.7.23)

Gemfile

source "https://rubygems.org"
gem "jrjackson", "=0.4.3"

crash.rb

require "jrjackson"

def parse(data)
  puts("enter parse")
  o = JrJackson::Ruby.parse("", {})
  puts("after JrJackson::Ruby.parse")
  puts("in load, o = #{o.inspect}") # this throws NPE
  o
end

result = JrJackson::Ruby.parse("", {}) # this works
puts("in main, result = #{result.inspect}")

result = parse("")
puts("parse result = #{result.inspect}")
$ bundle exec ruby crash.rb

in main, result = nil
enter parse
after JrJackson::Ruby.parse
Unhandled Java exception: java.lang.NullPointerException
java.lang.NullPointerException: null
              getClass at org/jruby/runtime/callsite/CachingCallSite.java:444
                  call at org/jruby/runtime/callsite/CachingCallSite.java:125
  invokeOther8:inspect at crash.rb:7
                 parse at crash.rb:7
                  call at org/jruby/internal/runtime/methods/CompiledIRMethod.java:168
          cacheAndCall at org/jruby/runtime/callsite/CachingCallSite.java:338
                  call at org/jruby/runtime/callsite/CachingCallSite.java:163
   invokeOther16:parse at crash.rb:14
                <main> at crash.rb:14
   invokeWithArguments at java/lang/invoke/MethodHandle.java:627
                  load at org/jruby/ir/Compiler.java:95
             runScript at org/jruby/Ruby.java:828
           runNormally at org/jruby/Ruby.java:747
           runNormally at org/jruby/Ruby.java:765
           runFromMain at org/jruby/Ruby.java:578
         doRunFromMain at org/jruby/Main.java:417
           internalRun at org/jruby/Main.java:305
                   run at org/jruby/Main.java:232
                  main at org/jruby/Main.java:204

Incoming fix PR.

Bad file descriptor error with Rails 3.2.X, Torquebox 3.1, JRuby 1.7.8

If I add 'jrjackson' to my gem file and restart my app (in dev or staging) I get on certain POSTs:

11:43:34,887 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/].[torquebox.static]] (http-/127.0.0.1:8080-3) JBWEB000236: Servlet.service() for servlet torquebox.static threw exception: org.jruby.exceptions.RaiseException: (Errno::EBADF) Bad file
 descriptor
        at org.jruby.RubyIO.close(org/jruby/RubyIO.java:2063) [jruby.jar:]

The Rails log shows that request comes in, but it doesn't get into the controller action. Once I remove the jrjackson gem and rebundle, the issue goes away.

Not sure what else I can give you to help diagnose or if I am misusing the gem (or doing something else stoopid)

Thoughts?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.