guyboertje / jrjackson Goto Github PK
View Code? Open in Web Editor NEWJruby wrapper for Jackson (and Smile)
Jruby wrapper for Jackson (and Smile)
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
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?
https://github.com/guyboertje/jrjackson/blame/master/lib/jrjackson/jrjackson.rb#L53
This is causing flaky test results in multi_json gem. Where it checks whether JSON was defined and not require 'json' again.
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}"
Can we make this one public?
https://github.com/guyboertje/jrjackson/blob/master/src/main/java/com/jrjackson/RubyJacksonModule.java#L20
This would allow setting custom options on that ObjectMapper
and not force the use of annotations to register custom types :)
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'
I believe there might be an issue when inspecting hashes produced by JrJackson::Json
, which doesn't occur when using JrJackson::Raw
.
Please see jruby/jruby#1211 for more information.
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})
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
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
.
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.
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 ?
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 .
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
For those who would like to use JrJackson in java projects it will be much convenient to get it from Maven Central. Thanks a lot!
Unable to spare time to actually hack these together, but here's a few suggestions.
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 :-)
I am not sure I understand why the method to_json
is not the first one looked up in serializeUnknownRubyObject
- https://github.com/guyboertje/jrjackson/blob/master/src/main/java/com/jrjackson/RubyAnySerializer.java#L74
IMO it should be the first method tried to control the serialization behaviour for any class by implementing, overriding or monkey-patching to_json
.
Is there a particular reason why it is the last one tried?
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?
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.
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.
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]
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>
Why can't we send the options to to_json method?
https://github.com/guyboertje/jrjackson/blob/master/lib/jrjackson/jrjackson.rb#L44
# 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?
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'
I am using jrjackson (0.4.2-java)
id = BSON::ObjectId.new
render json: JrJackson::Json.dump({id: id})
=> {"id": "2016-12-23 11:00:44 +0100"}
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.
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.
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
lib/jrjackson/jrjackson.rb points to "jars/jrjackson-1.2.19.jar" which has been replaced with "jars/jrjackson-1.2.20.jar".
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)'
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)
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\"}"
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.
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?
We are suffering from the issue FasterXML/jackson-core#216 (a continuation of FasterXML/jackson-core#207), which is resolved by jackson-core-2.6.2 (https://github.com/FasterXML/jackson-core/blob/jackson-core-2.6.2/release-notes/VERSION).
In our case (logstash), the problem disappears with jackson-* version 2.6.2
Would you mind to update the dependency of jrjackson to jackson-* to at least 2.6.2.
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
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
just added a same request on nokogiri: sparklemotion/nokogiri#1253
so please see the details there.
jrjackson uses jackson and leafy-rack pulls in https://github.com/lookout/leafy/blob/master/leafy-rack/leafy-rack.gemspec#L18 jackson as well.
so to avoid classloader conflicts due to different versions of the same jar are loaded it would be nice to use jar-dependencies which will avoid such cases.
$ 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.
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.
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.
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.
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;
}
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
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.
It looks like 2.8 is out, and 2.9 is close to release:
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?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.