我目前正在研究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)如何实现此功能(或者也有可能保护其他私有字段免受反射)。
一位同事指出,答案不是在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)); }
因此..这解决了如何保护字段的问题。但是,我仍然对为什么要实施这一点感到好奇。