RFR 8169653: Restore ObjectInputStream::resolveClass call stack default search order
Chris Hegarty
chris.hegarty at oracle.com
Tue Dec 6 11:27:19 UTC 2016
Mandy and I exchanged some mails off line, here is updated proposed wording.
> On 21 Nov 2016, at 09:41, Chris Hegarty <chris.hegarty at oracle.com> wrote:
>
> JDK-8155977 updated ObjectInputStream::resolveClass, and
> resolveProxyClass, to work with the platform class loader, but
> inadvertently removed the text describing the order in which the
> call stack is searched, for the 'loader'.
>
> The omission, from Java SE 8, is " ... closest such method to the
> currently executing frame". Similar text should be reinstated.
diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java
--- a/src/java.base/share/classes/java/io/ObjectInputStream.java
+++ b/src/java.base/share/classes/java/io/ObjectInputStream.java
@@ -640,46 +640,45 @@
/**
* Load the local class equivalent of the specified stream class
* description. Subclasses may implement this method to allow classes to
* be fetched from an alternate source.
*
* <p>The corresponding method in <code>ObjectOutputStream</code> is
* <code>annotateClass</code>. This method will be invoked only once for
* each unique class in the stream. This method can be implemented by
* subclasses to use an alternate loading mechanism but must return a
* <code>Class</code> object. Once returned, if the class is not an array
* class, its serialVersionUID is compared to the serialVersionUID of the
* serialized class, and if there is a mismatch, the deserialization fails
* and an {@link InvalidClassException} is thrown.
*
* <p>The default implementation of this method in
* <code>ObjectInputStream</code> returns the result of calling
* <pre>
* Class.forName(desc.getName(), false, loader)
* </pre>
- * where <code>loader</code> is determined as follows: if there is a
- * method on the current thread's stack whose declaring class is not a
- * <a href="../lang/ClassLoader.html#builtinLoaders">
- * <em>platform class</em></a>, then <code>loader</code> is
- * the class loader of such class; otherwise, <code>loader</code>
- * is the {@linkplain ClassLoader#getPlatformClassLoader()
+ * where <code>loader</code> is the first class loader on the current
+ * thread’s stack (starting from the currently executing method) that is
+ * neither the <a href="../lang/ClassLoader.html#builtinLoaders"><em>
+ * platform class loader</em></a> nor its ancestor; otherwise, <code>
+ * loaded</code> is the {@linkplain ClassLoader#getPlatformClassLoader()
* platform class loader}. If this call results in a
* <code>ClassNotFoundException</code> and the name of the passed
* <code>ObjectStreamClass</code> instance is the Java language keyword
* for a primitive type or void, then the <code>Class</code> object
* representing that primitive type or void will be returned
* (e.g., an <code>ObjectStreamClass</code> with the name
* <code>"int"</code> will be resolved to <code>Integer.TYPE</code>).
* Otherwise, the <code>ClassNotFoundException</code> will be thrown to
* the caller of this method.
*
* @param desc an instance of class <code>ObjectStreamClass</code>
* @return a <code>Class</code> object corresponding to <code>desc</code>
* @throws IOException any of the usual Input/Output exceptions.
* @throws ClassNotFoundException if class of a serialized object cannot
* be found.
*/
protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException
{
String name = desc.getName();
@@ -704,46 +703,45 @@
*
* <p>This method is called exactly once for each unique proxy class
* descriptor in the stream.
*
* <p>The corresponding method in <code>ObjectOutputStream</code> is
* <code>annotateProxyClass</code>. For a given subclass of
* <code>ObjectInputStream</code> that overrides this method, the
* <code>annotateProxyClass</code> method in the corresponding subclass of
* <code>ObjectOutputStream</code> must write any data or objects read by
* this method.
*
* <p>The default implementation of this method in
* <code>ObjectInputStream</code> returns the result of calling
* <code>Proxy.getProxyClass</code> with the list of <code>Class</code>
* objects for the interfaces that are named in the <code>interfaces</code>
* parameter. The <code>Class</code> object for each interface name
* <code>i</code> is the value returned by calling
* <pre>
* Class.forName(i, false, loader)
* </pre>
- * where <code>loader</code> is determined as follows: if there is a
- * method on the current thread's stack whose declaring class is not a
- * <a href="../lang/ClassLoader.html#builtinLoaders">
- * <em>platform class</em></a>, then <code>loader</code> is
- * the class loader of such class; otherwise, <code>loader</code>
- * is the {@linkplain ClassLoader#getPlatformClassLoader()
+ * where <code>loader</code> is the first class loader on the current
+ * thread’s stack (starting from the currently executing method) that is
+ * neither the <a href="../lang/ClassLoader.html#builtinLoaders"><em>
+ * platform class loader</em></a> nor its ancestor; otherwise, <code>
+ * loaded</code> is the {@linkplain ClassLoader#getPlatformClassLoader()
* platform class loader}.
* Unless any of the resolved interfaces are non-public, this same value
* of <code>loader</code> is also the class loader passed to
* <code>Proxy.getProxyClass</code>; if non-public interfaces are present,
* their class loader is passed instead (if more than one non-public
* interface class loader is encountered, an
* <code>IllegalAccessError</code> is thrown).
* If <code>Proxy.getProxyClass</code> throws an
* <code>IllegalArgumentException</code>, <code>resolveProxyClass</code>
* will throw a <code>ClassNotFoundException</code> containing the
* <code>IllegalArgumentException</code>.
*
* @param interfaces the list of interface names that were
* deserialized in the proxy class descriptor
* @return a proxy class for the specified interfaces
* @throws IOException any exception thrown by the underlying
* <code>InputStream</code>
* @throws ClassNotFoundException if the proxy class or any of the
* named interfaces could not be found
* @see ObjectOutputStream#annotateProxyClass(Class)
-Chris.
> [1] https://bugs.openjdk.java.net/browse/JDK-8155977
More information about the core-libs-dev
mailing list