Im więcej poznawałem moc java.lang.reflect.AccessibleObject.setAccessible
, tym bardziej jestem zdumiony tym, co on potrafi. Jest to zaadaptowane z mojej odpowiedzi na pytanie ( Używanie odbicia do zmiany statycznego pliku końcowego File.separatorChar do testowania jednostkowego ).
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"
}
}
Możesz robić naprawdę oburzające rzeczy:
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"
}
}
Przypuszczalnie projektanci API zdają sobie sprawę z tego, jak nadużycie setAccessible
może być, ale musieli przyznać, że ma to uzasadnione zastosowania, aby je zapewnić. Więc moje pytania to:
- Do czego służą prawdziwie uzasadnione zastosowania
setAccessible
?- Czy Java została zaprojektowana tak, aby w ogóle NIE miała takiej potrzeby?
- Jakie byłyby negatywne konsekwencje (jeśli w ogóle) takiego projektu?
- Czy możesz ograniczyć
setAccessible
się tylko do legalnych zastosowań?- Czy to tylko przez
SecurityManager
?- Jak to działa? Biała / czarna lista, szczegółowość itp.?
- Czy często trzeba go konfigurować w swoich aplikacjach?
- Czy mogę napisać moje klasy tak, aby były
setAccessible
odporne na działanie niezależnie odSecurityManager
konfiguracji?- Czy jestem na łasce tego, kto zarządza konfiguracją?
- Czy to tylko przez
Wydaje mi się, że jeszcze jedno ważne pytanie brzmi: CZY MUSZĘ SIĘ O TYM MARTWIEĆ ???
Żadne z moich zajęć nie przypomina egzekwowalnej prywatności. Wzór singletona (odkładając na bok wątpliwości co do jego zalet) jest teraz niemożliwy do wyegzekwowania. Jak pokazują powyższe fragmenty, nawet niektóre podstawowe założenia dotyczące działania języka Java nie są nawet bliskie zagwarantowania.
CZY TE PROBLEMY NIE SĄ PRAWDZIWE ???
OK, właśnie potwierdziłem: dzięki setAccessible
, napisy Java NIE są niezmienne.
import java.lang.reflect.*;
public class MutableStrings {
static void mutate(String s) throws Exception {
Field value = String.class.getDeclaredField("value");
value.setAccessible(true);
value.set(s, s.toUpperCase().toCharArray());
}
public static void main(String args[]) throws Exception {
final String s = "Hello world!";
System.out.println(s); // "Hello world!"
mutate(s);
System.out.println(s); // "HELLO WORLD!"
}
}
Czy tylko ja uważam, że to OGROMNY problem?