< prev index next >
src/java.base/share/classes/java/io/ObjectInputStream.java
Print this page
*** 417,426 ****
--- 417,437 ----
return readObjectOverride();
}
// if nested read, passHandle contains handle of enclosing object
int outerHandle = passHandle;
+ // save current cachedLoader
+ Object outerCL = cachedLoader;
+
+ Thread thread = Thread.currentThread();
+ if (outerCL == null ||
+ outerCL == thread ||
+ (outerCL instanceof CachedLoader &&
+ ((CachedLoader) outerCL).thread == thread)) {
+ // place mark so that latestUserDefinedLoader() can cache loader
+ cachedLoader = thread;
+ }
try {
Object obj = readObject0(false);
handles.markDependency(outerHandle, passHandle);
ClassNotFoundException ex = handles.lookupException(passHandle);
if (ex != null) {
*** 434,443 ****
--- 445,461 ----
} finally {
passHandle = outerHandle;
if (closed && depth == 0) {
clear();
}
+ if (outerCL == null ||
+ outerCL == thread ||
+ (outerCL instanceof CachedLoader &&
+ ((CachedLoader) outerCL).thread == thread)) {
+ // restore/clear cachedLoader when in correct thread/non-nested call
+ cachedLoader = outerCL;
+ }
}
}
/**
* This method is called by trusted subclasses of ObjectOutputStream that
*** 512,521 ****
--- 530,550 ----
* @since 1.4
*/
public Object readUnshared() throws IOException, ClassNotFoundException {
// if nested read, passHandle contains handle of enclosing object
int outerHandle = passHandle;
+ // save current cachedLoader
+ Object outerCL = cachedLoader;
+
+ Thread thread = Thread.currentThread();
+ if (outerCL == null ||
+ outerCL == thread ||
+ (outerCL instanceof CachedLoader &&
+ ((CachedLoader) outerCL).thread == thread)) {
+ // place mark so that latestUserDefinedLoader() can cache loader
+ cachedLoader = thread;
+ }
try {
Object obj = readObject0(true);
handles.markDependency(outerHandle, passHandle);
ClassNotFoundException ex = handles.lookupException(passHandle);
if (ex != null) {
*** 529,538 ****
--- 558,574 ----
} finally {
passHandle = outerHandle;
if (closed && depth == 0) {
clear();
}
+ if (outerCL == null ||
+ outerCL == thread ||
+ (outerCL instanceof CachedLoader &&
+ ((CachedLoader) outerCL).thread == thread)) {
+ // restore/clear cachedLoader when in correct thread/non-nested call
+ cachedLoader = outerCL;
+ }
}
}
/**
* Read the non-static and non-transient fields of the current class from
*** 2387,2404 ****
// REMIND: remove once hotspot inlines Double.longBitsToDouble
private static native void bytesToDoubles(byte[] src, int srcpos,
double[] dst, int dstpos,
int ndoubles);
/**
* Returns the first non-null and non-platform class loader (not counting
* class loaders of generated reflection implementation classes) up the
* execution stack, or the platform class loader if only code from the
* bootstrap and platform class loader is on the stack.
*/
! private static ClassLoader latestUserDefinedLoader() {
! return jdk.internal.misc.VM.latestUserDefinedLoader();
}
/**
* Default GetField implementation.
*/
--- 2423,2476 ----
// REMIND: remove once hotspot inlines Double.longBitsToDouble
private static native void bytesToDoubles(byte[] src, int srcpos,
double[] dst, int dstpos,
int ndoubles);
+ // cached latestUserDefinedLoader() result
+ private static class CachedLoader {
+ final ClassLoader loader;
+ final Thread thread = Thread.currentThread();
+
+ CachedLoader(ClassLoader loader) {
+ this.loader = loader;
+ }
+ }
+
+ // either null (when not called via public readObject() / readUnshared()), or
+ // a Thread instance (marking the thread that entered public readObject() /
+ // readUnshared() and is responsible for cleanup too), or
+ // a CachedLoader instance with cached loader
+ private Object cachedLoader;
+
/**
* Returns the first non-null and non-platform class loader (not counting
* class loaders of generated reflection implementation classes) up the
* execution stack, or the platform class loader if only code from the
* bootstrap and platform class loader is on the stack.
*/
! private ClassLoader latestUserDefinedLoader() {
! Object cl = cachedLoader;
! ClassLoader loader;
! Thread thread = Thread.currentThread();
! if (cl == thread) {
! // entered via public readObject() / readUnshared()
! // so we must evaluate loader lazily and cache it
! loader = jdk.internal.misc.VM.latestUserDefinedLoader();
! cachedLoader = new CachedLoader(loader);
! } else if (cl instanceof CachedLoader &&
! ((CachedLoader) cl).thread == thread) {
! // use cached value if correct thread
! loader = ((CachedLoader) cl).loader;
! } else {
! // not called via public readObject() / readUnshared():
! // (cl == null) or
! // invalid multi threaded use:
! // (cl != Thread.currentThread() && cl.thread != Thread.currentThread())
! // - don't cache
! loader = jdk.internal.misc.VM.latestUserDefinedLoader();
! }
! return loader;
}
/**
* Default GetField implementation.
*/
< prev index next >