Plus j'en ai appris sur le pouvoir 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 changer le fichier final statique 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"
}
}
Vraisemblablement, les concepteurs d'API réalisent à quel point il setAccessible
peut être abusif , mais doivent avoir admis qu'il a des utilisations légitimes pour le fournir. Donc mes questions sont:
- Quelles sont les utilisations vraiment légitimes
setAccessible
?- Java a-t-il été conçu pour 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 limiter
setAccessible
uniquement les utilisations légitimes?- Est-ce seulement à travers
SecurityManager
?- Comment ça marche? Liste blanche / liste noire, granularité, etc.?
- Est-il courant de devoir le configurer dans vos applications?
- Puis-je écrire mes cours pour être à l'
setAccessible
épreuve quelle que soit laSecurityManager
configuration?- Ou suis-je à la merci de celui qui gère la configuration?
- Est-ce seulement à travers
Je suppose qu'une autre question importante est: DOIS-JE M'INQUIÉTER DE CELA ???
Aucune de mes classes n'a le moindre semblant de confidentialité exécutoire. Le modèle singleton (mettant de côté les doutes sur ses mérites) est désormais impossible à appliquer. Comme le montrent mes extraits ci-dessus, même certaines hypothèses de base sur le fonctionnement de Java fondamental ne sont même pas proches d'être garanties.
CES PROBLÈMES NE SONT-ILS PAS RÉELS ???
D'accord, je viens de confirmer: grâce à setAccessible
, les chaînes Java ne sont PAS immuables.
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?