jrjackson
jrjackson copied to clipboard
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)
This is because simpledateformat isn't thread safe and DateTimeFormatter should be used instead (read more here)
"Offending" code is here https://github.com/guyboertje/jrjackson/blob/master/src/main/java/com/jrjackson/RubyAnySerializer.java#L233-L245