JDK 9 RFR of JDK-8168681: Correct deprecation text for Class.newInstance

joe darcy joe.darcy at oracle.com
Thu Nov 3 00:51:51 UTC 2016


Hello,

As found by Phil Race, the original substitution text for 
Class.newInstance (JDK-8159330) is not equivalent in all cases. This 
should be addressed. The current suggested replacement text is

"The call

  clazz.newInstance()

can be replaced by

  clazz.getConstructor().newInstance()"

The getConstructor call only returns *public* constructors while 
newInstance can call non-public constructors too, subject to the 
appropriate security checks.


Therefore, using "getDeclaredConstructor()" is a better replacement 
since it should be able to find and call non-public constructors when 
that is permissible. The patch for this is:

--- a/src/java.base/share/classes/java/lang/Class.java    Wed Nov 02 
16:24:43 2016 -0700
+++ b/src/java.base/share/classes/java/lang/Class.java    Wed Nov 02 
17:36:25 2016 -0700
@@ -485,7 +485,7 @@
       * can be replaced by
       *
       * <pre>{@code
-     * clazz.getConstructor().newInstance()
+     * clazz.getDeclaredConstructor().newInstance()
       * }</pre>
       *
       * The latter sequence of calls is inferred to be able to throw

I wrote a simple program to try calling constructors with different 
access levels private, protected, package (default), and public in 
different settings and in the cases I tested clazz.newInstance() and   
clazz.getConstructor().newInstance() agreed on both returning an object 
or both throwing an exception. This property also held when a security 
manager was enabled.

Doing a quick examination of the sources of java.lang.Class,

     public T newInstance()
         throws InstantiationException, IllegalAccessException
     {
         if (System.getSecurityManager() != null) {
             checkMemberAccess(Member.PUBLIC, 
Reflection.getCallerClass(), false);
         }

             // various things elided...
             try {
                 Class<?>[] empty = {};
                 final Constructor<T> c = getConstructor0(empty, 
Member.DECLARED);
                 // various more things elided...
             } catch (NoSuchMethodException e) {
                 throw (InstantiationException)
                     new InstantiationException(getName()).initCause(e);
             }
         }
             // still more things elided
     }

compared to

     public Constructor<T> getDeclaredConstructor(Class<?>... 
parameterTypes)
         throws NoSuchMethodException, SecurityException {
         checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), 
true);
         return getConstructor0(parameterTypes, Member.DECLARED);
     }

Both alternatives are wrappers around the lower-level getConstructor0 
method.

Thanks to Phil for noticing the problem with the existing text.

Cheers,

-Joe



More information about the core-libs-dev mailing list