简体   繁体   中英

Constructor.newInstance vs Class.newInstance with a SecurityManager

In Java, when a SecurityManager exists that rejects access check suppression, Constructor's newInstance method works while Class's newInstance throws a SecurityException. Here's an example:

import java.lang.reflect.ReflectPermission;
import java.security.Permission;

public class Test {
    public static void main(String[] args) throws Exception {
        System.setSecurityManager(new SecurityManager() {
            @Override
            public void checkPermission(Permission perm) {
                if (perm instanceof ReflectPermission && "suppressAccessChecks".equals(perm.getName())) {
                    throw new SecurityException();
                }
            }
        });

        String.class.getConstructor().newInstance(); // works
        String.class.newInstance(); // throws SecurityException
    }
}

Running this produces:

Exception in thread "main" java.lang.SecurityException
    at Test$1.checkPermission(Test.java:10)
    at java.lang.reflect.AccessibleObject.setAccessible(AccessibleObject.java:125)
    at java.lang.Class$1.run(Class.java:351)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.lang.Class.newInstance0(Class.java:348)
    at java.lang.Class.newInstance(Class.java:325)
    at Test.main(Test.java:16)

The JavaDoc for Class.newInstance says that it calls checkMemberAccess and checkPackageAccess on the SecurityManager, but I don't know why it would call setAccessible . Is there a rationale for this difference in behavior?

I'm using:

java version "1.6.0_20"
OpenJDK Runtime Environment (IcedTea6 1.9.5) (ArchLinux-6.b20_1.9.5-1-x86_64)
OpenJDK 64-Bit Server VM (build 17.0-b16, mixed mode)

Class.newInstance() invokes SecutrityManager.checkMemberAccess(this, Member.PUBLIC) , which - by default - grants access to all public members. checkPermission() is called (by checkMemberAccess() ) only if the member in question is not public .

Thus, your overriding of checkPermission() will not affect access to public members. You need to override checkMemberAccess() .

Here are the relevant quotes from the Javadocs of Class :

( newInstance() fails if) invocation of s.checkMemberAccess(this, Member.PUBLIC) denies creation of new instances of this class

And of SecurityManager :

The default policy (of checkMemberAccess() ) is to allow access to PUBLIC members, as well as access to classes that have the same class loader as the caller. In all other cases, this method calls checkPermission() ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM