8164908: ReflectionFactory support for IIOP and custom serialization
authorrriggs
Mon, 24 Oct 2016 14:52:51 -0400
changeset 41608 bb724835848f
parent 41607 57bbb18142ff
child 41609 f5a226a44fab
8164908: ReflectionFactory support for IIOP and custom serialization Summary: Add support for serialization to sun.reflect.ReflectionFactory Reviewed-by: alanb, chegar, plevart, amlu
jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java
jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java
jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java
jdk/test/com/sun/corba/serialization/ObjectStreamTest$_Echo_Stub.java
jdk/test/com/sun/corba/serialization/ObjectStreamTest$_Server_Tie.java
jdk/test/com/sun/corba/serialization/ObjectStreamTest.java
jdk/test/com/sun/corba/serialization/security.policy
jdk/test/sun/reflect/ReflectionFactory/NewConstructorForSerialization.java
jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java
jdk/test/sun/reflect/ReflectionFactory/security.policy
--- a/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java	Mon Oct 24 09:40:06 2016 -0400
+++ b/jdk/src/java.base/share/classes/java/io/ObjectStreamClass.java	Mon Oct 24 14:52:51 2016 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1413,27 +1413,7 @@
      * returned constructor (if any).
      */
     private static Constructor<?> getSerializableConstructor(Class<?> cl) {
-        Class<?> initCl = cl;
-        while (Serializable.class.isAssignableFrom(initCl)) {
-            if ((initCl = initCl.getSuperclass()) == null) {
-                return null;
-            }
-        }
-        try {
-            Constructor<?> cons = initCl.getDeclaredConstructor((Class<?>[]) null);
-            int mods = cons.getModifiers();
-            if ((mods & Modifier.PRIVATE) != 0 ||
-                ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
-                 !packageEquals(cl, initCl)))
-            {
-                return null;
-            }
-            cons = reflFactory.newConstructorForSerialization(cl, cons);
-            cons.setAccessible(true);
-            return cons;
-        } catch (NoSuchMethodException ex) {
-            return null;
-        }
+        return reflFactory.newConstructorForSerialization(cl);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java	Mon Oct 24 09:40:06 2016 -0400
+++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java	Mon Oct 24 14:52:51 2016 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,14 +25,25 @@
 
 package jdk.internal.reflect;
 
+import java.io.Externalizable;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.OptionalDataException;
+import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Field;
 import java.lang.reflect.Executable;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Modifier;
 import java.security.Permission;
 import java.security.PrivilegedAction;
+import java.util.Objects;
 import java.util.Properties;
+
 import sun.reflect.misc.ReflectUtil;
 import sun.security.action.GetPropertyAction;
 
@@ -57,6 +68,9 @@
     // Provides access to package-private mechanisms in java.lang.reflect
     private static volatile LangReflectAccess langReflectAccess;
 
+    /* Method for static class initializer <clinit>, or null */
+    private static volatile Method hasStaticInitializerMethod;
+
     //
     // "Inflation" mechanism. Loading bytecodes to implement
     // Method.invoke() and Constructor.newInstance() currently costs
@@ -337,16 +351,41 @@
     //
     //
 
-    public Constructor<?> newConstructorForSerialization
-        (Class<?> classToInstantiate, Constructor<?> constructorToCall)
-    {
-        // Fast path
-        if (constructorToCall.getDeclaringClass() == classToInstantiate) {
-            return constructorToCall;
+    public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
+        if (!Externalizable.class.isAssignableFrom(cl)) {
+            return null;
+        }
+        try {
+            Constructor<?> cons = cl.getConstructor();
+            cons.setAccessible(true);
+            return cons;
+        } catch (NoSuchMethodException ex) {
+            return null;
+        }
+    }
+
+    public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
+        Class<?> initCl = cl;
+        while (Serializable.class.isAssignableFrom(initCl)) {
+            if ((initCl = initCl.getSuperclass()) == null) {
+                return null;
+            }
+        }
+        Constructor<?> constructorToCall;
+        try {
+            constructorToCall = initCl.getDeclaredConstructor();
+            int mods = constructorToCall.getModifiers();
+            if ((mods & Modifier.PRIVATE) != 0 ||
+                    ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
+                            !packageEquals(cl, initCl))) {
+                return null;
+            }
+        } catch (NoSuchMethodException ex) {
+            return null;
         }
 
         ConstructorAccessor acc = new MethodAccessorGenerator().
-            generateSerializationConstructor(classToInstantiate,
+            generateSerializationConstructor(cl,
                                              constructorToCall.getParameterTypes(),
                                              constructorToCall.getExceptionTypes(),
                                              constructorToCall.getModifiers(),
@@ -364,9 +403,151 @@
                                           langReflectAccess().
                                           getConstructorParameterAnnotations(constructorToCall));
         setConstructorAccessor(c, acc);
+        c.setAccessible(true);
         return c;
     }
 
+    public final MethodHandle readObjectForSerialization(Class<?> cl) {
+        return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class);
+    }
+
+    public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
+        return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class);
+    }
+
+    public final MethodHandle writeObjectForSerialization(Class<?> cl) {
+        return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class);
+    }
+
+    private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl,
+                                                                   String methodName,
+                                                                   Class<?> streamClass) {
+        if (!Serializable.class.isAssignableFrom(cl)) {
+            return null;
+        }
+
+        try {
+            Method meth = cl.getDeclaredMethod(methodName, streamClass);
+            int mods = meth.getModifiers();
+            if (meth.getReturnType() != Void.TYPE ||
+                    Modifier.isStatic(mods) ||
+                    !Modifier.isPrivate(mods)) {
+                return null;
+            }
+            meth.setAccessible(true);
+            return MethodHandles.lookup().unreflect(meth);
+        } catch (NoSuchMethodException ex) {
+            return null;
+        } catch (IllegalAccessException ex1) {
+            throw new InternalError("Error", ex1);
+        }
+    }
+
+    /**
+     * Returns a MethodHandle for {@code writeReplace} on the serializable class
+     * or null if no match found.
+     * @param cl a serializable class
+     * @returnss the {@code writeReplace} MethodHandle or {@code null} if not found
+     */
+    public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
+        return getReplaceResolveForSerialization(cl, "writeReplace");
+    }
+
+    /**
+     * Returns a MethodHandle for {@code readResolve} on the serializable class
+     * or null if no match found.
+     * @param cl a serializable class
+     * @returns the {@code writeReplace} MethodHandle or {@code null} if not found
+     */
+    public final MethodHandle readResolveForSerialization(Class<?> cl) {
+        return getReplaceResolveForSerialization(cl, "readResolve");
+    }
+
+    /**
+     * Lookup readResolve or writeReplace on a class with specified
+     * signature constraints.
+     * @param cl a serializable class
+     * @param methodName the method name to find
+     * @returns a MethodHandle for the method or {@code null} if not found or
+     *       has the wrong signature.
+     */
+    private MethodHandle getReplaceResolveForSerialization(Class<?> cl,
+                                                           String methodName) {
+        if (!Serializable.class.isAssignableFrom(cl)) {
+            return null;
+        }
+
+        Class<?> defCl = cl;
+        while (defCl != null) {
+            try {
+                Method m = defCl.getDeclaredMethod(methodName);
+                if (m.getReturnType() != Object.class) {
+                    return null;
+                }
+                int mods = m.getModifiers();
+                if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) {
+                    return null;
+                } else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) {
+                    // fall through
+                } else if (Modifier.isPrivate(mods) && (cl != defCl)) {
+                    return null;
+                } else if (!packageEquals(cl, defCl)) {
+                    return null;
+                }
+                try {
+                    // Normal return
+                    m.setAccessible(true);
+                    return MethodHandles.lookup().unreflect(m);
+                } catch (IllegalAccessException ex0) {
+                    // setAccessible should prevent IAE
+                    throw new InternalError("Error", ex0);
+                }
+            } catch (NoSuchMethodException ex) {
+                defCl = defCl.getSuperclass();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns true if the given class defines a static initializer method,
+     * false otherwise.
+     */
+    public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
+        Method m = hasStaticInitializerMethod;
+        if (m == null) {
+            try {
+                m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer",
+                        new Class<?>[]{Class.class});
+                m.setAccessible(true);
+                hasStaticInitializerMethod = m;
+            } catch (NoSuchMethodException ex) {
+                throw new InternalError("No such method hasStaticInitializer on "
+                        + ObjectStreamClass.class, ex);
+            }
+        }
+        try {
+            return (Boolean) m.invoke(null, cl);
+        } catch (InvocationTargetException | IllegalAccessException ex) {
+            throw new InternalError("Exception invoking hasStaticInitializer", ex);
+        }
+    }
+
+    /**
+     * Return the accessible constructor for OptionalDataException signaling eof.
+     * @returns the eof constructor for OptionalDataException
+     */
+    public final Constructor<OptionalDataException> newOptionalDataExceptionForSerialization() {
+        try {
+            Constructor<OptionalDataException> boolCtor =
+                    OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE);
+            boolCtor.setAccessible(true);
+            return boolCtor;
+        } catch (NoSuchMethodException ex) {
+            throw new InternalError("Constructor not found", ex);
+        }
+    }
+
     //--------------------------------------------------------------------------
     //
     // Internals only below this point
@@ -426,4 +607,17 @@
         }
         return langReflectAccess;
     }
+
+    /**
+     * Returns true if classes are defined in the classloader and same package, false
+     * otherwise.
+     * @param cl1 a class
+     * @param cl2 another class
+     * @returns true if the two classes are in the same classloader and package
+     */
+    private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
+        return cl1.getClassLoader() == cl2.getClassLoader() &&
+                Objects.equals(cl1.getPackage(), cl2.getPackage());
+    }
+
 }
--- a/jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java	Mon Oct 24 09:40:06 2016 -0400
+++ b/jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java	Mon Oct 24 14:52:51 2016 -0400
@@ -25,24 +25,34 @@
 
 package sun.reflect;
 
+import java.io.OptionalDataException;
+import java.lang.invoke.MethodHandle;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.security.AccessController;
 import java.security.Permission;
 import java.security.PrivilegedAction;
 
+/**
+ * ReflectionFactory supports custom serialization.
+ * Its methods support the creation of uninitialized objects, invoking serialization
+ * private methods for readObject, writeObject, readResolve, and writeReplace.
+ * <p>
+ * ReflectionFactory access is restricted, if a security manager is active,
+ * unless the permission {@code RuntimePermission("reflectionFactoryAccess")}
+ * is granted.
+ */
 public class ReflectionFactory {
 
     private static final ReflectionFactory soleInstance = new ReflectionFactory();
-    private final jdk.internal.reflect.ReflectionFactory delegate;
-
-    private ReflectionFactory() {
-        delegate = AccessController.doPrivileged(
+    private static final jdk.internal.reflect.ReflectionFactory delegate = AccessController.doPrivileged(
             new PrivilegedAction<jdk.internal.reflect.ReflectionFactory>() {
                 public jdk.internal.reflect.ReflectionFactory run() {
                     return jdk.internal.reflect.ReflectionFactory.getReflectionFactory();
                 }
-        });
-    }
+            });
+
+    private ReflectionFactory() {}
 
     private static final Permission REFLECTION_FACTORY_ACCESS_PERM
             = new RuntimePermission("reflectionFactoryAccess");
@@ -53,7 +63,7 @@
      *
      * <p> First, if there is a security manager, its {@code checkPermission}
      * method is called with a {@link java.lang.RuntimePermission} with target
-     * {@code "reflectionFactoryAccess"}.  This may result in a securit
+     * {@code "reflectionFactoryAccess"}.  This may result in a security
      * exception.
      *
      * <p> The returned {@code ReflectionFactory} object should be carefully
@@ -61,6 +71,7 @@
      * data and invoke private methods, as well as to load unverified bytecodes.
      * It must never be passed to untrusted code.
      *
+     * @return the ReflectionFactory
      * @throws SecurityException if a security manager exists and its
      *         {@code checkPermission} method doesn't allow access to
      *         the RuntimePermission "reflectionFactoryAccess".
@@ -73,11 +84,129 @@
         return soleInstance;
     }
 
-    public Constructor<?> newConstructorForSerialization(Class<?> classToInstantiate,
-                                                         Constructor<?> constructorToCall)
+    /**
+     * Returns an accessible no-arg constructor for a class.
+     * The no-arg constructor is found searching the class and its supertypes.
+     *
+     * @param cl the class to instantiate
+     * @return a no-arg constructor for the class or {@code null} if
+     *     the class or supertypes do not have a suitable no-arg constructor
+     */
+    public final Constructor<?> newConstructorForSerialization(Class<?> cl)
     {
-        return delegate.newConstructorForSerialization(classToInstantiate,
-                                                       constructorToCall);
+        return delegate.newConstructorForSerialization(cl);
+    }
+
+    /**
+     * Returns an accessible no-arg constructor for an externalizable class to be
+     * initialized using a public no-argument constructor.
+     *
+     * @param cl the class to instantiate
+     * @return A no-arg constructor for the class; returns {@code null} if
+     *     the class does not implement {@link java.io.Externalizable}
+     */
+    public final Constructor<?> newConstructorForExternalization(Class<?> cl) {
+        return delegate.newConstructorForExternalization(cl);
+    }
+
+    /**
+     * Returns a direct MethodHandle for the {@code readObject} method on
+     * a Serializable class.
+     * The first argument of {@link MethodHandle#invoke} is the serializable
+     * object and the second argument is the {@code ObjectInputStream} passed to
+     * {@code readObject}.
+     *
+     * @param cl a Serializable class
+     * @return  a direct MethodHandle for the {@code readObject} method of the class or
+     *          {@code null} if the class does not have a {@code readObject} method
+     */
+    public final MethodHandle readObjectForSerialization(Class<?> cl) {
+        return delegate.readObjectForSerialization(cl);
+    }
+
+    /**
+     * Returns a direct MethodHandle for the {@code readObjectNoData} method on
+     * a Serializable class.
+     * The first argument of {@link MethodHandle#invoke} is the serializable
+     * object and the second argument is the {@code ObjectInputStream} passed to
+     * {@code readObjectNoData}.
+     *
+     * @param cl a Serializable class
+     * @return  a direct MethodHandle for the {@code readObjectNoData} method
+     *          of the class or {@code null} if the class does not have a
+     *          {@code readObjectNoData} method
+     */
+    public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) {
+        return delegate.readObjectNoDataForSerialization(cl);
+    }
+
+    /**
+     * Returns a direct MethodHandle for the {@code writeObject} method on
+     * a Serializable class.
+     * The first argument of {@link MethodHandle#invoke} is the serializable
+     * object and the second argument is the {@code ObjectOutputStream} passed to
+     * {@code writeObject}.
+     *
+     * @param cl a Serializable class
+     * @return  a direct MethodHandle for the {@code writeObject} method of the class or
+     *          {@code null} if the class does not have a {@code writeObject} method
+     */
+    public final MethodHandle writeObjectForSerialization(Class<?> cl) {
+        return delegate.writeObjectForSerialization(cl);
+    }
+
+    /**
+     * Returns a direct MethodHandle for the {@code readResolve} method on
+     * a serializable class.
+     * The single argument of {@link MethodHandle#invoke} is the serializable
+     * object.
+     *
+     * @param cl the Serializable class
+     * @return  a direct MethodHandle for the {@code readResolve} method of the class or
+     *          {@code null} if the class does not have a {@code readResolve} method
+     */
+    public final MethodHandle readResolveForSerialization(Class<?> cl) {
+        return delegate.readResolveForSerialization(cl);
+    }
+
+    /**
+     * Returns a direct MethodHandle for the {@code writeReplace} method on
+     * a serializable class.
+     * The single argument of {@link MethodHandle#invoke} is the serializable
+     * object.
+     *
+     * @param cl the Serializable class
+     * @return  a direct MethodHandle for the {@code writeReplace} method of the class or
+     *          {@code null} if the class does not have a {@code writeReplace} method
+     */
+    public final MethodHandle writeReplaceForSerialization(Class<?> cl) {
+        return delegate.writeReplaceForSerialization(cl);
+    }
+
+    /**
+     * Returns true if the class has a static initializer.
+     * The presence of a static initializer is used to compute the serialVersionUID.
+     * @param cl a serializable class
+     * @return {@code true} if the class has a static initializer,
+     *          otherwise {@code false}
+     */
+    public final boolean hasStaticInitializerForSerialization(Class<?> cl) {
+        return delegate.hasStaticInitializerForSerialization(cl);
+    }
+
+    /**
+     * Returns a new OptionalDataException with {@code eof} set to {@code true}
+     * or {@code false}.
+     * @param bool the value of {@code eof} in the created OptionalDataException
+     * @return  a new OptionalDataException
+     */
+    public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) {
+        Constructor<OptionalDataException> cons = delegate.newOptionalDataExceptionForSerialization();
+        try {
+            return cons.newInstance(bool);
+        } catch (InstantiationException|IllegalAccessException|InvocationTargetException ex) {
+            throw new InternalError("unable to create OptionalDataException", ex);
+        }
     }
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/corba/serialization/ObjectStreamTest$_Echo_Stub.java	Mon Oct 24 14:52:51 2016 -0400
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.rmi.UnexpectedException;
+
+import javax.rmi.CORBA.Stub;
+import javax.rmi.CORBA.Util;
+
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.portable.ApplicationException;
+import org.omg.CORBA.portable.OutputStream;
+import org.omg.CORBA.portable.RemarshalException;
+import org.omg.CORBA.portable.ServantObject;
+
+
+/**
+ * ObjectStreamTest$Echo Stub class generated by rmic, do not edit.
+ */
+public class ObjectStreamTest$_Echo_Stub extends Stub implements ObjectStreamTest.Echo {
+
+    private static final String[] _type_ids = {
+        "RMI:ObjectStreamTest\\U0024Echo:0000000000000000"
+    };
+
+    private static final long serialVersionUID = 5217577841494640354L;
+
+    public String[] _ids() {
+            return _type_ids.clone();
+        }
+
+        public Object echo(Object arg0) throws java.rmi.RemoteException {
+            if (!Util.isLocal(this)) {
+                try {
+                    org.omg.CORBA.portable.InputStream in = null;
+                    try {
+                        OutputStream out = _request("echo", true);
+                        Util.writeAny(out,arg0);
+                        in = _invoke(out);
+                        return Util.readAny(in);
+                    } catch (ApplicationException ex) {
+                        in = ex.getInputStream();
+                        String $_id = in.read_string();
+                        throw new UnexpectedException($_id);
+                    } catch (RemarshalException ex) {
+                        return echo(arg0);
+                    } finally {
+                        _releaseReply(in);
+                    }
+                } catch (SystemException ex) {
+                    throw Util.mapSystemException(ex);
+                }
+            } else {
+                ServantObject so = _servant_preinvoke("echo",ObjectStreamTest.Echo.class);
+                if (so == null) {
+                    return echo(arg0);
+                }
+                try {
+                    Object arg0Copy = Util.copyObject(arg0,_orb());
+                    Object result = ((ObjectStreamTest.Echo)so.servant).echo(arg0Copy);
+                    return Util.copyObject(result,_orb());
+                } catch (Throwable ex) {
+                    Throwable exCopy = (Throwable)Util.copyObject(ex,_orb());
+                    throw Util.wrapException(exCopy);
+                } finally {
+                    _servant_postinvoke(so);
+                }
+            }
+        }
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/corba/serialization/ObjectStreamTest$_Server_Tie.java	Mon Oct 24 14:52:51 2016 -0400
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.rmi.Remote;
+
+import javax.rmi.CORBA.Tie;
+import javax.rmi.CORBA.Util;
+
+import org.omg.CORBA.BAD_OPERATION;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.OutputStream;
+import org.omg.CORBA.portable.ResponseHandler;
+import org.omg.CORBA.portable.UnknownException;
+import org.omg.CORBA_2_3.portable.ObjectImpl;
+
+
+/**
+ * ObjectStreamClass$Echo server tie class generated by rmic, do not edit.
+ */
+public class ObjectStreamTest$_Server_Tie extends ObjectImpl implements Tie {
+
+    volatile private ObjectStreamTest.Server target = null;
+
+    private static final String[] _type_ids = {
+        "RMI:ObjectStreamTest\\U0024Echo:0000000000000000"
+    };
+
+    public void setTarget(Remote target) {
+        this.target = (ObjectStreamTest.Server) target;
+    }
+
+    public Remote getTarget() {
+        return target;
+    }
+
+    public org.omg.CORBA.Object thisObject() {
+        return this;
+    }
+
+    public void deactivate() {
+        _orb().disconnect(this);
+        _set_delegate(null);
+        target = null;
+    }
+
+    public ORB orb() {
+        return _orb();
+    }
+
+    public void orb(ORB orb) {
+        orb.connect(this);
+    }
+
+    public String[] _ids() {
+        return _type_ids.clone();
+    }
+
+    public OutputStream  _invoke(String method, InputStream _in, ResponseHandler reply) throws SystemException {
+        try {
+            ObjectStreamTest.Server target = this.target;
+            if (target == null) {
+                throw new java.io.IOException();
+            }
+            org.omg.CORBA_2_3.portable.InputStream in =
+                (org.omg.CORBA_2_3.portable.InputStream) _in;
+            if (method.equals("echo")) {
+                Object arg0 = Util.readAny(in);
+                Object result = target.echo(arg0);
+                OutputStream out = reply.createReply();
+                Util.writeAny(out,result);
+                return out;
+            }
+            throw new BAD_OPERATION();
+        } catch (SystemException ex) {
+            throw ex;
+        } catch (Throwable ex) {
+            throw new UnknownException(ex);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/corba/serialization/ObjectStreamTest.java	Mon Oct 24 14:52:51 2016 -0400
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.time.LocalTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Objects;
+import java.util.PropertyPermission;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.LongAdder;
+
+import javax.naming.CommunicationException;
+import javax.naming.InitialContext;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.rmi.CORBA.Util;
+import javax.rmi.PortableRemoteObject;
+
+import org.omg.CORBA_2_3.ORB;
+import org.omg.CORBA_2_3.portable.OutputStream;
+import org.omg.CORBA_2_3.portable.InputStream;
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.JDKToolLauncher;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import org.testng.TestNG;
+
+/*
+ * @test
+ * @library /test/lib
+ * @build jdk.test.lib.*
+ * @compile  ObjectStreamTest.java  ObjectStreamTest$_Echo_Stub.java  ObjectStreamTest$_Server_Tie.java
+ * @modules java.corba/com.sun.corba.se.impl.io java.base/java.io java.corba/com.sun.corba.se.impl.activation
+ * @summary Tests of ReflectionFactory use in IIOP Serialization
+ * @run testng/othervm
+ *       -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
+ *       -Djava.naming.provider.url=iiop://localhost:1050 ObjectStreamTest
+ * @run testng/othervm/policy=security.policy
+ *       -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
+ *       -Djava.naming.provider.url=iiop://localhost:1050 ObjectStreamTest
+ */
+
+@Test
+public class ObjectStreamTest {
+
+    enum Colors {RED, GREEN, YELLOW}
+
+    static Set<Colors> colorSet = new HashSet<>();
+
+    static {
+        colorSet.add(Colors.RED);
+        colorSet.add(Colors.GREEN);
+    }
+
+    /**
+     * The process spawned to run orbd.
+     */
+    static Process orbdProcess;
+    static Thread orbThread;
+
+    @DataProvider(name = "Objects")
+    static Object[][] patterns() {
+        BigInteger bigInteger = new BigInteger("8943892002309239");
+        InetAddress inetAddr;
+        try {
+            inetAddr = java.net.InetAddress.getByAddress(new byte[]{127, 0, 0, 1});
+        } catch (UnknownHostException ignored) {
+            inetAddr = null;
+            // ignored
+        }
+        HashMap<String, Object> hashMap = new HashMap<>();
+        hashMap.put("BigInteger", bigInteger);
+        hashMap.put("InetAddress", inetAddr);
+        hashMap.put("String", "bString");
+        Object[][] patterns = new Object[][]{
+                {"aString"},
+                {Integer.valueOf(5)},
+                {new SimpleObject(4, 4.0f)},
+                {Arrays.asList("a", "b", "c")},
+                {new String[]{"x", "y", "z"}},
+                {new ArrayList<Object>(1)},     // uses readObject/writeObject
+                {new StringBuffer("abc")},      // Has serialPersistentFields
+                {new StringBuilder("abc")},
+                {Colors.RED},
+                {inetAddr},
+                {LocalTime.MIDNIGHT},           // uses writeReplace/readResolve
+                {new LongAdder()},              // uses writeReplace/readResolve
+                {EnumSet.allOf(Colors.class)},  // used writeReplace/readResolve
+                {bigInteger},
+                {new BigDecimal(bigInteger)},
+                {hashMap},
+                {new PropertyPermission("abc", "read")}, // has serialPersistentFields
+        };
+        return patterns;
+    }
+
+
+    /**
+     * Check ObjectStreamClass facts match between core serialization and CORBA.
+     *
+     * @param value
+     */
+    @Test(dataProvider = "Objects")
+    static void factCheck(Serializable value) {
+        Class<?> clazz = value.getClass();
+        java.io.ObjectStreamClass sOSC = java.io.ObjectStreamClass.lookup(clazz);
+        java.io.ObjectStreamField[] sFields = sOSC.getFields();
+        com.sun.corba.se.impl.io.ObjectStreamClass cOSC = corbaLookup(clazz);
+        com.sun.corba.se.impl.io.ObjectStreamField[] cFields = cOSC.getFields();
+
+        Assert.assertEquals(sFields.length, cFields.length, "Different number of fields");
+        for (int i = 0; i < sFields.length; i++) {
+            Assert.assertEquals(sFields[i].getName(), cFields[i].getName(), "different field names " + cFields[i].getName());
+            Assert.assertEquals(sFields[i].getType(), cFields[i].getType(), "different field types " + cFields[i].getName());
+            Assert.assertEquals(sFields[i].getTypeString(), cFields[i].getTypeString(), "different field typestrings " + cFields[i].getName());
+        }
+
+        Assert.assertEquals(baseMethod("hasReadObjectMethod", sOSC, (Class<?>[]) null),
+                corbaMethod("hasReadObject", cOSC, (Class<?>[]) null), "hasReadObject: " + value.getClass());
+
+        Assert.assertEquals(baseMethod("hasWriteObjectMethod", sOSC, (Class<?>[]) null),
+                corbaMethod("hasWriteObject", cOSC, (Class<?>[]) null), "hasWriteObject: " + value.getClass());
+
+        Assert.assertEquals(baseMethod("hasWriteReplaceMethod", sOSC, (Class<?>[]) null),
+                corbaMethod("hasWriteReplaceMethod", cOSC, (Class<?>[]) null), "hasWriteReplace: " + value.getClass());
+
+        Assert.assertEquals(baseMethod("hasReadResolveMethod", sOSC, (Class<?>[]) null),
+                corbaMethod("hasReadResolveMethod", cOSC, (Class<?>[]) null), "hasReadResolve: " + value.getClass());
+
+        Assert.assertEquals(baseMethod("getSerialVersionUID", sOSC, (Class<?>[]) null),
+                corbaMethod("getSerialVersionUID", cOSC, (Class<?>[]) null), "getSerialVersionUID: " + value.getClass());
+
+    }
+
+
+    /**
+     * Test that objects written using Util.writeAny can be serialized
+     * and deserialized using Util.readAny to equivalent objects.
+     */
+    @Test(dataProvider = "Objects", enabled = true, dependsOnMethods = {"factCheck"})
+    static void WriteValueObjectStreamTest01(Serializable value) throws Exception {
+        ORB orb = (ORB) ORB.init(new String[0], null);
+
+        OutputStream out = (OutputStream) orb.create_output_stream();
+        Util.writeAny(out, value);
+
+        InputStream in = (InputStream) out.create_input_stream();
+        Object actual = Util.readAny(in);
+
+        checkEquals(actual, value);
+    }
+
+    /**
+     * Test that objects can be echoed to a server and come back equivalent.
+     */
+    @Test(dataProvider = "Objects", enabled = true, dependsOnMethods = {"factCheck"})
+    static void echoObjects(Serializable value) throws Exception {
+        Context initialNamingContext = Server.init();
+        Echo echo = (Echo) PortableRemoteObject.narrow(
+                initialNamingContext.lookup(Server.serverID), Echo.class);
+        Object actual = echo.echo(value);
+        checkEquals(actual, value);
+    }
+
+    /**
+     * Check if the value and result are equals, with some tests depending on the type.
+     * @param expected the expected value
+     * @param actual the actual value
+     */
+    static void checkEquals(Object actual, Object expected) {
+        Class<?> cl = expected.getClass();
+        Assert.assertEquals(actual.getClass(), cl, "type of value not equal to class of result");
+        try {
+            if (cl.isArray() || !(cl.getDeclaredMethod("equals", cl) == null)) {
+                Assert.assertEquals(actual, expected, "echo'd object not equal");
+            } else {
+                Assert.assertEquals(toString(actual), toString(expected), "toString values not equal");
+            }
+        } catch (NoSuchMethodException ex) {
+            Assert.assertEquals(toString(actual), toString(expected), "toString values not equal");
+        }
+    }
+
+    /**
+     * Convert an object to a String, and correctly for arrays.
+     * @param obj an object
+     * @return the tostring for the object.
+     */
+    static String toString(Object obj) {
+        return obj.getClass().isArray()
+                ? Arrays.toString((Object[]) obj)
+                : Objects.toString(obj);
+    }
+
+    /**
+     * SimpleObject to test round trip.
+     */
+    static class SimpleObject implements Serializable {
+        private static final long serialVersionUID = 5217577841494640354L;
+
+        private int i = 0;
+        private float f = 0.0f;
+
+        SimpleObject(int i, float f) {
+            this.i = i;
+            this.f = f;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            SimpleObject that = (SimpleObject) o;
+
+            if (i != that.i) return false;
+            return Float.compare(that.f, f) == 0;
+
+        }
+
+        @Override
+        public int hashCode() {
+            int result = i;
+            result = 31 * result + (f != +0.0f ? Float.floatToIntBits(f) : 0);
+            return result;
+        }
+
+        @Override
+        public String toString() {
+            return "SimpleObject{" +
+                    "i=" + i +
+                    ", f=" + f +
+                    '}';
+        }
+    }
+
+
+    /**
+     * Lookup the CORBA ObjectStreamClass instance for a class.
+     * @param clazz the class
+     * @return the CORBA ObjectStreamClass instance for the class
+     */
+    static com.sun.corba.se.impl.io.ObjectStreamClass corbaLookup(Class<?> clazz) {
+        Class<?> oscClass = com.sun.corba.se.impl.io.ObjectStreamClass.class;
+
+        try {
+            Method meth = oscClass.getDeclaredMethod("lookup", Class.class);
+            meth.setAccessible(true);
+            return (com.sun.corba.se.impl.io.ObjectStreamClass) meth.invoke(null, clazz);
+        } catch (NoSuchMethodException noMeth) {
+            throw new RuntimeException("missing method", noMeth);
+        } catch (IllegalAccessException | InvocationTargetException rex) {
+            throw new RuntimeException("invocation failed", rex);
+        }
+    }
+
+    /**
+     * Lookup aand invoke method on a serializable object via the CORBA ObjectStreamClass.
+     * @param methodName method name
+     * @param osc CORBA ObjectStreamClass
+     * @param argClasses method arguments
+     * @return the value returned from invoking the method
+     */
+    static Object corbaMethod(String methodName, com.sun.corba.se.impl.io.ObjectStreamClass osc, Class<?>... argClasses) {
+        Class<?> oscClass = com.sun.corba.se.impl.io.ObjectStreamClass.class;
+
+        try {
+            Method meth = oscClass.getDeclaredMethod(methodName, argClasses);
+            meth.setAccessible(true);
+            return meth.invoke(osc);
+
+        } catch (NoSuchMethodException noMeth) {
+            throw new RuntimeException("missing method" + osc.getName()
+                    + "::" + methodName, noMeth);
+        } catch (IllegalAccessException | InvocationTargetException rex) {
+            throw new RuntimeException("invocation failed", rex);
+        }
+    }
+
+
+    /**
+     * Lookup aand invoke method on a serializable object via java.io.ObjectStreamClass.
+     * @param methodName method name
+     * @param osc java.io.ObjectStreamClass
+     * @param argClasses method arguments
+     * @return the value returned from invoking the method
+     */
+    static Object baseMethod(String methodName, java.io.ObjectStreamClass osc, Class<?>... argClasses) {
+        Class<?> oscClass = java.io.ObjectStreamClass.class;
+
+        try {
+            Method meth = oscClass.getDeclaredMethod(methodName, argClasses);
+            meth.setAccessible(true);
+            return meth.invoke(osc);
+
+        } catch (NoSuchMethodException noMeth) {
+            throw new RuntimeException("missing method: " + osc.getName()
+                    + "::" + methodName, noMeth);
+        } catch (IllegalAccessException | InvocationTargetException rex) {
+            throw new RuntimeException("invocation failed", rex);
+        }
+    }
+
+    /**
+     * Simple echo interface to check serialization/deserialization.
+     */
+    interface Echo extends Remote {
+        Object echo(Object obj) throws RemoteException;
+    }
+
+    static class Server extends PortableRemoteObject implements Echo {
+
+        public static final String serverID = "ObjectStreamTestServer";
+
+        private static Context initialNamingContext;
+
+        private static Server server;
+
+        public Server() throws RemoteException {
+            super();
+        }
+
+        public Object echo(Object obj) {
+            return obj;
+        }
+
+
+        public static Context init() {
+            if (initialNamingContext == null) {
+                try {
+                    startOrbd();
+                    Thread.sleep(5000L);        // Give it 5 seconds
+                } catch (Exception eex) {
+                    throw new RuntimeException("Orbd", eex);
+                }
+                for (int i = 0; i < 1; i++) {
+                    try {
+                        Thread.sleep(1L);
+                        initialNamingContext = new InitialContext();
+                        server = new Server();
+                        initialNamingContext.rebind(serverID, server);
+                    } catch (CommunicationException | InterruptedException cex) {
+                        System.out.printf("retry #%d sec: ex: %s%n", i, cex);
+                    } catch (NamingException ex) {
+                        throw new RuntimeException("can't initialize naming context", ex);
+                    } catch (RemoteException rex) {
+                        throw new RuntimeException("can't initialize server", rex);
+                    }
+                }
+            }
+            if (initialNamingContext == null) {
+                Assert.fail("Can't initialize the Orb, no naming context");
+            }
+            return initialNamingContext;
+        }
+    }
+
+    static void startOrbd() throws Exception {
+        System.out.println("\nStarting orbd with NS port 1050 ");
+        JDKToolLauncher orbdLauncher = JDKToolLauncher.create("orbd")
+                        .addToolArg("-ORBInitialHost").addToolArg("localhost")
+                        .addToolArg("-ORBInitialPort").addToolArg("1050");
+
+        System.out.println("ObjectStreamTest: Executing: " + Arrays.asList(orbdLauncher.getCommand()));
+        ProcessBuilder pb = new ProcessBuilder(orbdLauncher.getCommand());
+
+        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
+        orbdProcess = pb.start();
+    }
+
+    @AfterSuite
+    static void killOrbd() throws Exception {
+        if (orbdProcess != null) {
+            orbdProcess.destroyForcibly();
+            orbdProcess.waitFor();
+            System.out.printf("destroyed orbd, pid: %d, exitValue: %d%n",
+                    orbdProcess.getPid(), orbdProcess.exitValue());
+        }
+    }
+
+
+
+    // Main can be used to run the tests from the command line with only testng.jar.
+    @SuppressWarnings("raw_types")
+    @Test(enabled = false)
+    public static void main(String[] args) {
+        Class<?>[] testclass = {ObjectStreamTest.class};
+        TestNG testng = new TestNG();
+        testng.setTestClasses(testclass);
+        testng.run();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/corba/serialization/security.policy	Mon Oct 24 14:52:51 2016 -0400
@@ -0,0 +1,15 @@
+// Individual Permissions for ObjectStreamTest
+grant {
+        // Permissions needed to run the test
+        permission java.util.PropertyPermission "*", "read";
+        permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete,execute";
+        permission java.net.SocketPermission "*", "resolve,connect,listen,accept";
+
+        // Permissions to allow ObjectTest to use IIOP ObjectStreamClass
+        permission java.lang.RuntimePermission "accessClassInPackage.com.sun.corba.se.impl.io";
+        permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+        permission java.lang.RuntimePermission "accessDeclaredMembers";
+        permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect";
+        permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
+        permission java.io.SerializablePermission "enableSubclassImplementation";
+};
--- a/jdk/test/sun/reflect/ReflectionFactory/NewConstructorForSerialization.java	Mon Oct 24 09:40:06 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8137058
- * @summary Basic test for the unsupported newConstructorForSerialization
- * @modules jdk.unsupported
- */
-
-import java.lang.reflect.Constructor;
-import sun.reflect.ReflectionFactory;
-
-public class NewConstructorForSerialization {
-
-    private static Constructor<?> getConstructor(Class<?> type)
-        throws NoSuchMethodException
-    {
-        ReflectionFactory factory = ReflectionFactory.getReflectionFactory();
-        Constructor<?> objectConstructor = type.getConstructor((Class[]) null);
-
-        @SuppressWarnings("unchecked")
-        Constructor<?> c = (Constructor<?>) factory
-                .newConstructorForSerialization(type, objectConstructor);
-        return c;
-    }
-
-    public static void main(String[] args) throws Exception {
-        System.out.println(getConstructor(Object.class).newInstance());
-        System.out.println(getConstructor(Foo.class).newInstance());
-        System.out.println(getConstructor(Bar.class).newInstance());
-    }
-
-    static class Foo {
-        public Foo() { }
-    }
-
-    static class Bar extends Foo {
-        public Bar() { }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java	Mon Oct 24 14:52:51 2016 -0400
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.OptionalDataException;
+import java.io.Serializable;
+import java.lang.invoke.MethodHandle;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import sun.reflect.ReflectionFactory;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import org.testng.TestNG;
+
+/*
+ * @test
+ * @bug 8137058 8164908
+ * @run testng ReflectionFactoryTest
+ * @run testng/othervm/policy=security.policy ReflectionFactoryTest
+ * @summary Basic test for the unsupported ReflectionFactory
+ * @modules jdk.unsupported
+ */
+
+public class ReflectionFactoryTest {
+
+    // Initialized by init()
+    static ReflectionFactory factory;
+
+    @DataProvider(name = "ClassConstructors")
+    static Object[][] classConstructors() {
+        return new Object[][] {
+                {Object.class},
+                {Foo.class},
+                {Bar.class},
+        };
+    }
+
+    @BeforeClass
+    static void init() {
+        factory = ReflectionFactory.getReflectionFactory();
+    }
+
+    /**
+     * Test that the correct Constructor is selected and run.
+     * @param type type of object to create
+     * @throws NoSuchMethodException - error
+     * @throws InstantiationException - error
+     * @throws IllegalAccessException - error
+     * @throws InvocationTargetException - error
+     */
+    @Test(dataProvider="ClassConstructors")
+    static void testConstructor(Class<?> type)
+        throws NoSuchMethodException, InstantiationException,
+            IllegalAccessException, InvocationTargetException
+    {
+        @SuppressWarnings("unchecked")
+        Constructor<?> c = factory.newConstructorForSerialization(type);
+
+        Object o = c.newInstance();
+        Assert.assertEquals(o.getClass(), type, "Instance is wrong type");
+        if (o instanceof Foo) {
+            Foo foo = (Foo)o;
+            foo.check();
+        }
+    }
+
+    static class Foo {
+        private int foo;
+        public Foo() {
+            this.foo = 1;
+        }
+
+        public String toString() {
+            return "foo: " + foo;
+        }
+
+        public void check() {
+            int expectedFoo = 1;
+            Assert.assertEquals(foo, expectedFoo, "foo() constructor not run");
+        }
+    }
+
+    static class Bar extends Foo implements Serializable {
+        private int bar;
+        public Bar() {
+            this.bar = 1;
+        }
+
+        public String toString() {
+            return super.toString() + ", bar: " + bar;
+        }
+
+        public void check() {
+            super.check();
+            int expectedBar = 0;
+            Assert.assertEquals(bar, expectedBar, "bar() constructor not run");
+        }
+    }
+
+    /**
+     * Test newConstructorForExternalization returns the constructor and it can be called.
+     * @throws NoSuchMethodException - error
+     * @throws InstantiationException - error
+     * @throws IllegalAccessException - error
+     * @throws InvocationTargetException - error
+     */
+    @Test
+    static void newConstructorForExternalization()
+            throws NoSuchMethodException, InstantiationException,
+            IllegalAccessException, InvocationTargetException {
+        Constructor<?> cons = factory.newConstructorForExternalization(Ext.class);
+        Ext ext = (Ext)cons.newInstance();
+        Assert.assertEquals(ext.ext, 1, "Constructor not run");
+    }
+
+    static class Ext implements Externalizable {
+        private static final long serialVersionUID = 1L;
+
+        int ext;
+
+        public Ext() {
+            ext = 1;
+        }
+
+        @Override
+        public void writeExternal(ObjectOutput out) throws IOException {}
+
+        @Override
+        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {}
+    }
+
+    @Test
+    static void testReadWriteObjectForSerialization() throws Throwable {
+        MethodHandle readObjectMethod = factory.readObjectForSerialization(Ser.class);
+        Assert.assertNotNull(readObjectMethod, "readObjectMethod not found");
+
+        MethodHandle readObjectNoDataMethod = factory.readObjectNoDataForSerialization(Ser.class);
+        Assert.assertNotNull(readObjectNoDataMethod, "readObjectNoDataMethod not found");
+
+        MethodHandle writeObjectMethod = factory.writeObjectForSerialization(Ser.class);
+        Assert.assertNotNull(writeObjectMethod, "writeObjectMethod not found");
+
+        MethodHandle readResolveMethod = factory.readResolveForSerialization(Ser.class);
+        Assert.assertNotNull(readResolveMethod, "readResolveMethod not found");
+
+        MethodHandle writeReplaceMethod = factory.writeReplaceForSerialization(Ser.class);
+        Assert.assertNotNull(writeReplaceMethod, "writeReplaceMethod not found");
+
+        byte[] data = null;
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+            Ser ser = new Ser();
+
+            writeReplaceMethod.invoke(ser);
+            Assert.assertTrue(ser.writeReplaceCalled, "writeReplace not called");
+            Assert.assertFalse(ser.writeObjectCalled, "writeObject should not have been called");
+
+            writeObjectMethod.invoke(ser, oos);
+            Assert.assertTrue(ser.writeReplaceCalled, "writeReplace should have been called");
+            Assert.assertTrue(ser.writeObjectCalled, "writeObject not called");
+            oos.flush();
+            data = baos.toByteArray();
+        }
+
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
+             ObjectInputStream ois = new ObjectInputStream(bais)) {
+            Ser ser2 = new Ser();
+
+            readObjectMethod.invoke(ser2, ois);
+            Assert.assertTrue(ser2.readObjectCalled, "readObject not called");
+            Assert.assertFalse(ser2.readObjectNoDataCalled, "readObjectNoData should not be called");
+            Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called");
+
+            readObjectNoDataMethod.invoke(ser2, ois);
+            Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called");
+            Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called");
+            Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called");
+
+            readResolveMethod.invoke(ser2);
+            Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called");
+            Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called");
+            Assert.assertTrue(ser2.readResolveCalled, "readResolve not called");
+        }
+    }
+
+    @Test
+    static void hasStaticInitializer() {
+        boolean actual = factory.hasStaticInitializerForSerialization(Ser.class);
+        Assert.assertTrue(actual, "hasStaticInitializerForSerialization is wrong");
+    }
+
+    static class Ser implements Serializable {
+        private static final long serialVersionUID = 2L;
+        static {
+            // Define a static class initialization method
+        }
+
+        boolean readObjectCalled = false;
+        boolean readObjectNoDataCalled = false;
+        boolean writeObjectCalled = false;
+        boolean readResolveCalled = false;
+        boolean writeReplaceCalled = false;
+
+        public Ser() {}
+
+        private void readObject(ObjectInputStream ois) throws IOException {
+            Assert.assertFalse(writeObjectCalled, "readObject called too many times");
+            readObjectCalled = ois.readBoolean();
+        }
+
+        private void readObjectNoData(ObjectInputStream ois) throws IOException {
+            Assert.assertFalse(readObjectNoDataCalled, "readObjectNoData called too many times");
+            readObjectNoDataCalled = true;
+        }
+
+        private void writeObject(ObjectOutputStream oos) throws IOException {
+            Assert.assertFalse(writeObjectCalled, "writeObject called too many times");
+            writeObjectCalled = true;
+            oos.writeBoolean(writeObjectCalled);
+        }
+
+        private Object writeReplace() {
+            Assert.assertFalse(writeReplaceCalled, "writeReplace called too many times");
+            writeReplaceCalled = true;
+            return this;
+        }
+
+        private Object readResolve() {
+            Assert.assertFalse(readResolveCalled, "readResolve called too many times");
+            readResolveCalled = true;
+            return this;
+        }
+    }
+
+    /**
+     * Test the constructor of OptionalDataExceptions.
+     */
+    @Test
+    static void newOptionalDataException() {
+        OptionalDataException ode = factory.newOptionalDataExceptionForSerialization(true);
+        Assert.assertTrue(ode.eof, "eof wrong");
+        ode = factory.newOptionalDataExceptionForSerialization(false);
+        Assert.assertFalse(ode.eof, "eof wrong");
+
+    }
+
+
+
+    // Main can be used to run the tests from the command line with only testng.jar.
+    @SuppressWarnings("raw_types")
+    @Test(enabled = false)
+    public static void main(String[] args) {
+        Class<?>[] testclass = {ReflectionFactoryTest.class};
+        TestNG testng = new TestNG();
+        testng.setTestClasses(testclass);
+        testng.run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/reflect/ReflectionFactory/security.policy	Mon Oct 24 14:52:51 2016 -0400
@@ -0,0 +1,11 @@
+// Individual Permissions for ReflectionFactoryTest
+grant {
+        // Permissions needed to run the test
+        permission java.util.PropertyPermission "*", "read";
+        permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete,execute";
+
+        permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+        permission java.lang.RuntimePermission "accessDeclaredMembers";
+        permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect";
+        permission java.lang.RuntimePermission "reflectionFactoryAccess";
+};