8155977: ObjectInputStream::resolveClass & resolveProxyClass for platform loader
authormchung
Thu, 12 May 2016 11:16:56 -0700
changeset 37899 1b8ec90a1e15
parent 37898 ac36c71a44f9
child 37900 8e5fcef42caa
8155977: ObjectInputStream::resolveClass & resolveProxyClass for platform loader Reviewed-by: acorn, alanb, chegar, dfuchs
jdk/make/mapfiles/libjava/mapfile-vers
jdk/src/java.base/share/classes/java/io/ObjectInputStream.java
jdk/src/java.base/share/classes/jdk/internal/misc/VM.java
jdk/src/java.base/share/native/libjava/VM.c
jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java
--- a/jdk/make/mapfiles/libjava/mapfile-vers	Thu May 12 16:33:37 2016 +0100
+++ b/jdk/make/mapfiles/libjava/mapfile-vers	Thu May 12 11:16:56 2016 -0700
@@ -262,7 +262,7 @@
 		Java_jdk_internal_reflect_Reflection_getCallerClass__;
 		Java_jdk_internal_reflect_Reflection_getCallerClass__I;
 		Java_jdk_internal_reflect_Reflection_getClassAccessFlags;
-		Java_jdk_internal_misc_VM_latestUserDefinedLoader;
+		Java_jdk_internal_misc_VM_latestUserDefinedLoader0;
                 Java_jdk_internal_misc_VM_getuid;
                 Java_jdk_internal_misc_VM_geteuid;
                 Java_jdk_internal_misc_VM_getgid;
--- a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java	Thu May 12 16:33:37 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java	Thu May 12 11:16:56 2016 -0700
@@ -603,12 +603,12 @@
      *     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 was
-     * defined by a user-defined class loader (and was not a generated to
-     * implement reflective invocations), then <code>loader</code> is class
-     * loader corresponding to the closest such method to the currently
-     * executing frame; otherwise, <code>loader</code> is
-     * <code>null</code>. If this call results in 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()
+     * 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
@@ -666,12 +666,15 @@
      * <pre>
      *     Class.forName(i, false, loader)
      * </pre>
-     * where <code>loader</code> is that of the first non-<code>null</code>
-     * class loader up the execution stack, or <code>null</code> if no
-     * non-<code>null</code> class loaders are on the stack (the same class
-     * loader choice used by the <code>resolveClass</code> method).  Unless any
-     * of the resolved interfaces are non-public, this same value of
-     * <code>loader</code> is also the class loader passed to
+     * 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()
+     * 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
@@ -2154,10 +2157,11 @@
                                               int ndoubles);
 
     /**
-     * Returns the first non-null class loader (not counting class loaders of
-     * generated reflection implementation classes) up the execution stack, or
-     * null if only code from the null class loader is on the stack.  This
-     * method is also called via reflection by the following RMI-IIOP class:
+     * Returns the first non-null and non-platform class loader
+     * (not counting class loaders of generated reflection implementation classes)
+     * up the execution stack, or null if only code from the bootstrap and
+     * platform class loader is on the stack.
+     * This method is also called via reflection by the following RMI-IIOP class:
      *
      *     com.sun.corba.se.internal.util.JDKClassLoader
      *
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java	Thu May 12 16:33:37 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/VM.java	Thu May 12 11:16:56 2016 -0700
@@ -390,10 +390,25 @@
     private static final int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020;
 
     /*
-     * 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.
+     * Returns the first user-defined class loader up the execution stack,
+     * or the platform class loader if only code from the platform or
+     * bootstrap class loader is on the stack.
      */
-    public static native ClassLoader latestUserDefinedLoader();
+    public static ClassLoader latestUserDefinedLoader() {
+        ClassLoader loader = latestUserDefinedLoader0();
+        return loader != null ? loader : ClassLoader.getPlatformClassLoader();
+    }
+
+    /*
+     * Returns the first user-defined class loader up the execution stack,
+     * or null if only code from the platform or bootstrap class loader is
+     * on the stack.  VM does not keep a reference of platform loader and so
+     * it returns null.
+     *
+     * This method should be replaced with StackWalker::walk and then we can
+     * remove the logic in the VM.
+     */
+    private static native ClassLoader latestUserDefinedLoader0();
 
     /**
      * Returns {@code true} if we are in a set UID program.
--- a/jdk/src/java.base/share/native/libjava/VM.c	Thu May 12 16:33:37 2016 +0100
+++ b/jdk/src/java.base/share/native/libjava/VM.c	Thu May 12 11:16:56 2016 -0700
@@ -36,7 +36,7 @@
 };
 
 JNIEXPORT jobject JNICALL
-Java_jdk_internal_misc_VM_latestUserDefinedLoader(JNIEnv *env, jclass cls) {
+Java_jdk_internal_misc_VM_latestUserDefinedLoader0(JNIEnv *env, jclass cls) {
     return JVM_LatestUserDefinedLoader(env);
 }
 
--- a/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java	Thu May 12 16:33:37 2016 +0100
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/MarshalInputStream.java	Thu May 12 11:16:56 2016 -0700
@@ -194,7 +194,7 @@
         /*
          * Unless we were told to skip this consideration, choose the
          * "default loader" to simulate the default ObjectInputStream
-         * resolveClass mechanism (that is, choose the first non-null
+         * resolveClass mechanism (that is, choose the first non-platform
          * loader on the execution stack) to maximize the likelihood of
          * type compatibility with calling code.  (This consideration
          * is skipped during server parameter unmarshalling using the 1.2
@@ -268,8 +268,9 @@
     }
 
     /*
-     * 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.
+     * Returns the first non-platform class loader up the execution stack,
+     * or platform class loader if only code from the platform class loader or null
+     * is on the stack.
      */
     private static ClassLoader latestUserDefinedLoader() {
         return jdk.internal.misc.VM.latestUserDefinedLoader();