-
Notifications
You must be signed in to change notification settings - Fork 514
Description
Abstract:
When deserializing an object, the classes of nested objects (e.g. objects contained in an ArrayList) are loaded with the sun.misc.Launcher$AppClassLoader that has loaded spring-loaded itself instead of the classloader of the calling code.
Background:
When deserializing objects, the ObjectInputStream uses sun.misc.VM.latestUserDefinedLoader() to get the ClassLoader to resolve the classes that are read from the input stream.
If the class that invoked deserialization is loaded by a custom class loader, e.g. the WebappClassLoader within a web application, this class loader is used to load the classes of the object to be deserialized.
The contract of sun.misc.VM.latestUserDefinedLoader() is:
Returns the first non-null class loader up the execution stack,
or null if only code from the null class loader is on the stack.
Under spring-loaded, reflective method calls are intercepted. So when ObjectStreamClass.invokeReadObject() uses reflection to call ArrayList<E>.readObject(), this call is intercepted by ReflectiveInterceptor.jlrMethodInvoke(). When ObjectInputStream.resolveClass() is then invoked by ArrayList<E>.readObject(), the first non-null class loader on a stack frame is the sun.misc.Launcher$AppClassLoader that has been used to load ReflectiveInterceptor.jlrMethodInvoke().
Here is a sample call stack that illustrates this issue. The class loader in each stack frame is listed in square brackets at the end of the line. Stack Frames without a ClassLoader at the end use the null class loader (i.e. system loader).
ObjectInputStream.resolveClass(ObjectStreamClass) line: 623
ObjectInputStream.readNonProxyDesc(boolean) line: 1610
ObjectInputStream.readClassDesc(boolean) line: 1515
ObjectInputStream.readOrdinaryObject(boolean) line: 1769
ObjectInputStream.readObject0(boolean) line: 1348
ObjectInputStream.readObject() line: 370 [local variables unavailable]
ArrayList<E>.readObject(ObjectInputStream) line: 771
GeneratedMethodAccessor417.invoke(Object, Object[]) line: not available
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 606
ReflectiveInterceptor.jlrMethodInvoke(Method, Object, Object...) line: 1270 [sun.misc.Launcher$AppClassLoader]
GeneratedMethodAccessor339.invoke(Object, Object[]) line: not available
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43
Method.invoke(Object, Object...) line: 606
ObjectStreamClass.__sljlrmi(Method, Object, Object[]) line: not available
ObjectStreamClass.invokeReadObject(Object, ObjectInputStream) line: 1017
ObjectInputStream.readSerialData(Object, ObjectStreamClass) line: 1891
ObjectInputStream.readOrdinaryObject(boolean) line: 1796
ObjectInputStream.readObject0(boolean) line: 1348
ObjectInputStream.readObject() line: 370
SerializationUtils.deserialize(InputStream) line: 230 [org.springsource.loaded.ChildClassLoader]
SerializationUtils.deserialize(byte[]) line: 273 [org.springsource.loaded.ChildClassLoader]