When calling a servlet with more than 2 threads, ocassionaly io#read returns an empty string. After further investigation, we determined that to_io is returning the same IO objects to multiple ruby threads. Therefore once one thread read the content of the IO, the second thread reading the shared IO gets an empty string back.
The problem is located @ $jruby-rack_home/src/main/java/org/jruby/rack/DefaultRackApplication.java
Headius suggested to define the method "to_io" with getSingletonClass() instead of getMetaClass().
After following headius recommendation, the problem went away.
The getSingletonClass change is probably the simplest option, but I think we should consider defining the to_io method once and having it access either a field on RackEnvironment or an instance variable on the ruby side. Redefining the method every time will cost, as will having all requests execute against a new singletonized object.