RFR 8169653: Restore ObjectInputStream::resolveClass call stack default search order

Daniel Fuchs daniel.fuchs at oracle.com
Tue Dec 6 11:35:08 UTC 2016


Hi Chris,

Is that a typo? I see it at two places:

otherwise, <code>
+     * loaded</code> is the {@linkplain 
ClassLoader#getPlatformClassLoader()
       * platform class loader}.

("loaded" vs "loader")

best regards,

-- daniel

On 06/12/16 11:27, Chris Hegarty wrote:
> 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