我目前正在研究java的安全性,发现了一个奇怪的现象。java中的安全存储在java.lang.System中的SecurityManager字段中。有趣的是,该字段似乎受到保护,以防止反射访问,这确实有意义,但据我所知,这个字段是唯一有意义的。下面是一个例子:
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年的这个描述访问这个字段的blog post ),我想知道a)这是不是作为一个快速修复来实现的,以防止通过反射轻松禁用securitymanager;b)这是如何实现的(或者更确切地说,有没有可能保护其他私有字段不受反射的影响)。
发布于 2013-07-23 16:54:48
一位同事指出,答案不在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.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));
}所以..。这解决了如何保护字段的问题。然而,我仍然很好奇为什么要实现这一点。
发布于 2013-07-23 04:35:11
首先,防止反射的方法可能是在字段获取机制下的JVM中的一个脏if:
if (strcmp(field, "security") == 0 && strcmp(class, "java.lang.System")) {
return NULL;(我并不是说这就是JVM中的实际代码!)
这显然对大多数java用户是不可访问的,所以唯一的其他选择是安装一个安全管理器,它禁止私有字段和方法访问。这是可能的,但我不确定是怎么做的。
https://stackoverflow.com/questions/17796815
复制相似问题