Plus j'en apprenais sur le pouvoir de java.lang.reflect.AccessibleObject.setAccessible
plus je suis étonné de ce qu'il peut faire. Ceci est adapté de ma réponse à la question ( Utilisation de la réflexion pour modifier le fichier statique final File.separatorChar pour les tests unitaires ).
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"
}
}
Vous pouvez faire des choses vraiment scandaleuses :
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"
}
}
On peut supposer que les concepteurs de l'API se rendent compte de l'utilisation abusive setAccessible
peut être, mais doit avoir concédé qu'il a des utilisations légitimes pour le fournir. Donc mes questions sont :
- Quelles sont les utilisations vraiment légitimes de
setAccessible
?- Java aurait-il pu être conçu de manière à ne pas avoir ce besoin en premier lieu ?
- Quelles seraient les conséquences négatives (le cas échéant) d'une telle conception ?
- Pouvez-vous restreindre
setAccessible
à des fins légitimes uniquement ?- Est-ce que c'est seulement par
SecurityManager
?- Comment cela fonctionne-t-il ? Liste blanche/liste noire, granularité, etc ?
- Est-il courant de devoir le configurer dans vos applications ?
- Puis-je écrire mes classes pour qu'elles soient
setAccessible
-sans tenir compte deSecurityManager
configuration ?- Ou suis-je à la merci de celui qui gère la configuration ?
- Est-ce que c'est seulement par
Je suppose qu'une question plus importante est : DOIS-JE M'INQUIÉTER DE CELA ?
Aucun de mes cours n'a un semblant de confidentialité applicable, quel qu'il soit. Le modèle singleton (en mettant de côté les doutes sur ses mérites) est maintenant impossible à appliquer. Comme le montrent mes extraits ci-dessus, même certaines hypothèses de base sur le fonctionnement fondamental de Java sont loin d'être garanties.
CES PROBLÈMES NE SONT-ILS PAS RÉELS ?
Ok, je viens de confirmer : grâce à setAccessible
les chaînes de caractères Java sont PAS immuable.
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!"
}
}
Suis-je le seul à penser que c'est une énorme préoccupation ?
30 votes
Vous devriez voir ce qu'ils peuvent faire en C++ ! (Oh, et probablement en C#.)