小编典典

保护字段不被反射-System.security的奇怪情况

java

我目前正在研究Java安全性,并遇到了一个奇怪的现象。Java中的SecurityManager存储在java.lang.System中的“
security”字段中。有趣的是,该领域似乎受到了防止反射访问的保护,这确实是有道理的,但是据我所知,该领域是唯一的领域。因此,这是示例:

for(Field f : System.class.getDeclaredFields())
    System.out.println(f);

输出

public static final java.io.InputStream java.lang.System.in
public static final java.io.PrintStream java.lang.System.out
public static final java.io.PrintStream java.lang.System.err
private static volatile java.io.Console java.lang.System.cons
private static java.util.Properties java.lang.System.props
private static java.lang.String java.lang.System.lineSeparator

有趣的是:该字段声明为

private static volatile SecurityManager security = null;

不在列表中,并且确定有足够的呼叫

System.class.getDeclaredField("security");

产生NoSuchFieldException。由于我在网上找不到有关此内容的任何信息,而且我很确定该字段以前可以通过反射来访问(另请参见,例如,2010年的博客文章中描述了如何访问此字段),我想知道a)是否已实现作为一种快速解决方案,可以防止通过反射轻松禁用安全管理器,以及b)如何实现此功能(或者也有可能保护其他私有字段免受反射)。


阅读 209

收藏
2020-11-13

共1个答案

小编典典

一位同事指出,答案不是在jvm中,而是在jdk中,更确切地说是在sun.reflect.Reflection类中。在这里,您会发现执行以下操作的静态初始化程序

static {
    Map<Class,String[]> map = new HashMap<Class,String[]>();
    map.put(Reflection.class,
        new String[] {"fieldFilterMap", "methodFilterMap"});
    map.put(System.class, new String[] {"security"});
    fieldFilterMap = map;

    methodFilterMap = new HashMap<Class,String[]>();
}

现在,如果我们稍微看一下java.lang.Class中的getDeclaredFields方法,我们将发现使用对Reflection类的调用来过滤字段:

Reflection.filterFields(this, getDeclaredFields0(publicOnly));

其中filterFields实现为

public static Field[] filterFields(Class containingClass,
                                   Field[] fields) {
    if (fieldFilterMap == null) {
        // Bootstrapping
        return fields;
    }
    return (Field[])filter(fields, fieldFilterMap.get(containingClass));
}

因此..这解决了如何保护字段的问题。但是,我仍然对为什么要实施这一点感到好奇。

2020-11-13