I am currently looking into java security and came across a strange phenomenon. The SecurityManager in java is stored in the field "security" in java.lang.System. Interestingly, the field seems to be protected against reflective access, which does make sense, but as far as I know this field is the only one which is. So here is the example:
for(Field f : System.class.getDeclaredFields())
System.out.println(f);
outputs
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
Interestingly: the field declared as
private static volatile SecurityManager security = null;
is not in the list, and sure enough a call to
System.class.getDeclaredField("security");
yields a NoSuchFieldException. As I couldn't find anything about this online, and I am pretty sure this field used to be accessible via reflection (see also, for example, this blog post from 2010 which describes accessing this field) I was wondering a) was this implemented as a quick fix to prevent easily disabling the securitymanager via reflection and b) how this is implemented (or rather is there any chance of protecting other private fields from reflection as well).
A colleague pointed out that the answer is not in the jvm but in the jdk, more precisely in the class sun.reflect.Reflection. There you'll find a static initializer that does the following
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[]>();
}
If we now look a bit closer at the getDeclaredFields method in java.lang.Class we'll find that the fields are filtered using a call to the Reflection class:
Reflection.filterFields(this, getDeclaredFields0(publicOnly));
where filterFields is implemented as
public static Field[] filterFields(Class containingClass,
Field[] fields) {
if (fieldFilterMap == null) {
// Bootstrapping
return fields;
}
return (Field[])filter(fields, fieldFilterMap.get(containingClass));
}
So .. this solves the issue how the field is protected. I am however still curious as to why this was implemented.
First, the way this was prevented from reflection was probably a dirty if
in the JVM under the field getting mechanism:
if (strcmp(field, "security") == 0 && strcmp(class, "java.lang.System")) {
return NULL;
(I am NOT meaning to imply that this is the actual code in the JVM!!)
This obviously is not accesible to most users of java, so the only other option is to install a security manager that disallows private field and method access. This is possible, but I'm not sure how.