How to limit setAccessible to only "legitimate" uses?
- by polygenelubricants
The more I learned about the power of setAccessible, the more astonished I am at what it can do. This is adapted from my answer to the question (Using reflection to change static final File.separatorChar for unit testing).
import java.lang.reflect.*;
public class EverythingIsTrue {
static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
public static void main(String args[]) throws Exception {
setFinalStatic(Boolean.class.getField("FALSE"), true);
System.out.format("Everything is %s", false); // "Everything is true"
}
}
You can do truly outrageous stuff:
public class UltimateAnswerToEverything {
static Integer[] ultimateAnswer() {
Integer[] ret = new Integer[256];
java.util.Arrays.fill(ret, 42);
return ret;
}
public static void main(String args[]) throws Exception {
EverythingIsTrue.setFinalStatic(
Class.forName("java.lang.Integer$IntegerCache")
.getDeclaredField("cache"),
ultimateAnswer()
);
System.out.format("6 * 9 = %d", 6 * 9); // "6 * 9 = 42"
}
}
Presumably the API designers realize how abusable setAccessible can be, but must have conceded that it has legitimate uses to provide it. So my questions are:
What are the truly legitimate uses for setAccessible?
Could Java has been designed as to NOT have this need in the first place?
What would the negative consequences (if any) of such design be?
Can you restrict setAccessible to legitimate uses only?
Is it only through SecurityManager?
How does it work? Whitelist/blacklist, granularity, etc?
Is it common to have to configure it in your applications?