Quanto mais aprendo sobre o poder do java.lang.reflect.AccessibleObject.setAccessible
, mais espantado fico com o que ele pode fazer. Isso foi adaptado de minha resposta à pergunta ( Usando reflexão para alterar File.separatorChar final estático para teste de unidade ).
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"
}
}
Você pode fazer coisas verdadeiramente ultrajantes:
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"
}
}
Presumivelmente, os designers da API percebem o quão abusivo setAccessible
pode ser, mas devem ter admitido que ela tem usos legítimos para fornecê-la. Então, minhas perguntas são:
- Para que são os usos verdadeiramente legítimos
setAccessible
?- O Java poderia ter sido projetado para NÃO ter essa necessidade em primeiro lugar?
- Quais seriam as consequências negativas (se houver) de tal projeto?
- Você pode restringir apenas
setAccessible
para usos legítimos?- É apenas através
SecurityManager
?- Como funciona? Whitelist / blacklist, granularity, etc?
- É comum ter que configurá-lo em seus aplicativos?
- Posso escrever minhas aulas para serem à
setAccessible
prova, independentemente daSecurityManager
configuração?- Ou estou à mercê de quem gerencia a configuração?
- É apenas através
Acho que mais uma pergunta importante é: PRECISO ME PREOCUPAR COM ISSO ???
Nenhuma das minhas aulas tem qualquer aparência de privacidade obrigatória. O padrão singleton (colocando de lado as dúvidas sobre seus méritos) agora é impossível de aplicar. Como mostram meus trechos acima, mesmo algumas suposições básicas de como funciona o Java fundamental não estão nem perto de serem garantidas.
ESTES PROBLEMAS NÃO SÃO REAIS ???
Ok, acabei de confirmar: graças a setAccessible
, strings Java NÃO são imutáveis.
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!"
}
}
Eu sou o único que acha que isso é uma grande preocupação?