8168980: Reinstate sun.reflect.ReflectionFactory.newConstructorForSerialization(Class,Constructor)
authorchegar
Tue, 01 Nov 2016 12:37:29 +0000
changeset 41827 710feffff038
parent 41826 b35ee9b35b09
child 41828 0436ea0c6099
8168980: Reinstate sun.reflect.ReflectionFactory.newConstructorForSerialization(Class,Constructor) Reviewed-by: alanb
jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java
jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java
jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java
--- a/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java	Mon Oct 31 14:09:42 2016 -0700
+++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java	Tue Nov 01 12:37:29 2016 +0000
@@ -364,6 +364,16 @@
         }
     }
 
+    public final Constructor<?> newConstructorForSerialization(Class<?> cl,
+                                                               Constructor<?> constructorToCall)
+    {
+        if (constructorToCall.getDeclaringClass() == cl) {
+            constructorToCall.setAccessible(true);
+            return constructorToCall;
+        }
+        return generateConstructor(cl, constructorToCall);
+    }
+
     public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
         Class<?> initCl = cl;
         while (Serializable.class.isAssignableFrom(initCl)) {
@@ -383,6 +393,12 @@
         } catch (NoSuchMethodException ex) {
             return null;
         }
+        return generateConstructor(cl, constructorToCall);
+    }
+
+    private final Constructor<?> generateConstructor(Class<?> cl,
+                                                     Constructor<?> constructorToCall) {
+
 
         ConstructorAccessor acc = new MethodAccessorGenerator().
             generateSerializationConstructor(cl,
--- a/jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java	Mon Oct 31 14:09:42 2016 -0700
+++ b/jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java	Tue Nov 01 12:37:29 2016 +0000
@@ -85,6 +85,21 @@
     }
 
     /**
+     * Returns an accessible constructor capable of creating instances
+     * of the given class, initialized by the given constructor.
+     *
+     * @param cl the class to instantiate
+     * @param constructorToCall the constructor to call
+     * @return an accessible constructor
+     */
+    public Constructor<?> newConstructorForSerialization(Class<?> cl,
+                                                         Constructor<?> constructorToCall)
+    {
+        return delegate.newConstructorForSerialization(cl,
+                                                       constructorToCall);
+    }
+
+    /**
      * Returns an accessible no-arg constructor for a class.
      * The no-arg constructor is found searching the class and its supertypes.
      *
--- a/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java	Mon Oct 31 14:09:42 2016 -0700
+++ b/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java	Tue Nov 01 12:37:29 2016 +0000
@@ -45,7 +45,7 @@
 
 /*
  * @test
- * @bug 8137058 8164908
+ * @bug 8137058 8164908 8168980
  * @run testng ReflectionFactoryTest
  * @run testng/othervm/policy=security.policy ReflectionFactoryTest
  * @summary Basic test for the unsupported ReflectionFactory
@@ -95,6 +95,47 @@
         }
     }
 
+    @DataProvider(name = "NonSerialConstructors")
+    static Object[][] constructors() throws NoSuchMethodException {
+        return new Object[][] {
+                {Foo.class, Object.class.getDeclaredConstructor()},
+                {Foo.class, Foo.class.getDeclaredConstructor()},
+                {Baz.class, Object.class.getDeclaredConstructor()},
+                {Baz.class, Foo.class.getDeclaredConstructor()},
+                {Baz.class, Baz.class.getDeclaredConstructor()}
+        };
+    }
+
+    /**
+     * Tests that the given Constructor, in the hierarchy, is run.
+     */
+    @Test(dataProvider="NonSerialConstructors")
+    static void testNonSerializableConstructor(Class<?> cl,
+                                               Constructor<?> constructorToCall)
+        throws ReflectiveOperationException
+    {
+        @SuppressWarnings("unchecked")
+        Constructor<?> c = factory.newConstructorForSerialization(cl,
+                                                                  constructorToCall);
+
+        Object o = c.newInstance();
+        Assert.assertEquals(o.getClass(), cl, "Instance is wrong type");
+
+        int expectedFoo = 0;
+        int expectedBaz = 0;
+        if (constructorToCall.getName().equals("ReflectionFactoryTest$Foo")) {
+            expectedFoo = 1;
+        } else if (constructorToCall.getName().equals("ReflectionFactoryTest$Baz")) {
+            expectedFoo = 1;
+            expectedBaz = 4;
+        }
+
+        Assert.assertEquals(((Foo)o).foo(), expectedFoo);
+        if (o instanceof Baz) {
+            Assert.assertEquals(((Baz)o).baz(), expectedBaz);
+        }
+    }
+
     static class Foo {
         private int foo;
         public Foo() {
@@ -109,6 +150,8 @@
             int expectedFoo = 1;
             Assert.assertEquals(foo, expectedFoo, "foo() constructor not run");
         }
+
+        public int foo() { return foo; }
     }
 
     static class Bar extends Foo implements Serializable {
@@ -128,6 +171,12 @@
         }
     }
 
+    static class Baz extends Foo {
+        private final int baz;
+        public Baz() { this.baz = 4; }
+        public int baz() { return baz; }
+    }
+
     /**
      * Test newConstructorForExternalization returns the constructor and it can be called.
      * @throws NoSuchMethodException - error