jrjackson icon indicating copy to clipboard operation
jrjackson copied to clipboard

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

Open robbavey opened this issue 5 years ago • 1 comments

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)

robbavey avatar Sep 23 '19 15:09 robbavey

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

jsvd avatar Sep 23 '19 15:09 jsvd