使用SecurityManager的Constructor.newInstance vs Class.newInstance

时间:2011-02-05 19:08:03

标签: java reflection

在Java中,当存在拒绝访问检查抑制的SecurityManager时,Constructor的newInstance方法可以工作,而Class的newInstance会抛出SecurityException。这是一个例子:

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
    }
}

运行它会产生:

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)

Class.newInstance的JavaDoc表示它在SecurityManager上调用checkMemberAccess和checkPackageAccess,但我不知道它为什么会调用setAccessible。这种行为差异是否存在理由?

我正在使用:

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)

1 个答案:

答案 0 :(得分:0)

Class.newInstance()调用SecutrityManager.checkMemberAccess(this, Member.PUBLIC),默认情况下,授予对所有公共成员的访问权限。仅当相关成员公开时,才会checkPermission()调用checkMemberAccess()

因此,覆盖checkPermission()不会影响对公共成员的访问。您需要覆盖checkMemberAccess()

以下是来自Class的Javadocs的相关引用:

  

newInstance()失败,如果)调用s.checkMemberAccess(this,Member.PUBLIC)拒绝创建此类的新实例

SecurityManager

  

默认策略(checkMemberAccess())是允许访问PUBLIC成员,以及访问与调用者具有相同类加载器的类。在所有其他情况下,此方法调用 checkPermission() ...