OpenJ9’s Advantage for Java Serialization

Did you know… that just by using OpenJ9 as your runtime, applications using deserialization could gain a huge performance advantage?

Background

Java serialization provides a way to easily convert a sequence of bytes to and from a java.lang.Object.

One step that occurs during the process of deserialization is loading the class specified by the class descriptor in the stream of bytes. This involves calling two methods that contribute to slow performance:

  • java.lang.Class.forName

See https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#forName-java.lang.String-boolean-java.lang.ClassLoader-

  • java.io.ObjectInputStream.latestUserDefinedLoader

This is a private method that finds the latest user defined classloader or “LUDCL” to use with Class.forName. If first acquires VM access which means its safe to examine VM data structures and walk the stack. It then walks the stack to find the most recent ClassLoader which is an expensive action.

Optimization

In OpenJ9 there are two optimizations at work:

  1. Class caching: create a java.io.ClassCache to reduce calls to java.lang.Class.forName for repeated lookups
  2. Cache “LUDCL”: The loader can be safely cached while in the ObjectInputStream class. If custom readObject methods are invoked during this process the LUDCL will need to be refreshed.
  3. JIT replacing ObjectInputStream.readObject: To eliminate another LUDCL retrieval, the JIT will replace ObjectInputStream.readObject() call with ObjectInputStream.redirectedReadObject(ObjectInputStream iStream, Class caller). ObjectInputStream.redirectedReadObject will provide the LUDCL information through an argument preventing extra calls to LUDCL.

Performance results for Java 8

With these optimizations enabled we are seeing as much as a 4% improvement in application throughput.
 
Picture2
 

How can I take advantage of this?

This deserialization goodness will be enabled by default starting with OpenJ9’s 0.18.0 release this January, 2020 for all Java versions.

In the meantime to ensure you are making the most of OpenJ9’s performance advantage you can enable the option with the com.ibm.enableClassCaching property. See our documentation for more details.

One comment

  1. This should probably link to the Javadoc for ObjectInputStream.resolveClass, since that Javadoc is what explains how the LUDCL is actually used.

Leave a Reply