Чем больше я узнал о силе java.lang.reflect.AccessibleObject.setAccessible
, тем больше я был удивлен тем, что он может сделать. Это адаптировано из моего ответа на вопрос (Использование отражения для изменения статического финального файла File.separatorChar для модульного тестирования).
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"
}
}
Вы можете делать поистине возмутительные вещи:
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"
}
}
Предположительно, разработчики API понимают, насколько неприхотливым может быть setAccessible
, но он должен признать, что он имеет законные цели для его предоставления. Поэтому мои вопросы:
- Каковы действительно законные цели использования
setAccessible
?- Может ли Java быть спроектирована так, чтобы НЕ иметь эту потребность в первую очередь?
- Каковы были бы негативные последствия (если таковые имеются) такого дизайна?
- Можете ли вы ограничить
setAccessible
только законным использованием?- Это только через
SecurityManager
?- Как это работает? Белый список/черный список, зернистость и т.д.
- Обычно ли вам приходится настраивать его в своих приложениях?
- Могу ли я написать свои классы как
setAccessible
-защищенный, независимо от конфигурацииSecurityManager
?- Или я во власти того, кто управляет конфигурацией?
- Это только через
Я предполагаю, что еще один важный вопрос: мне нужно заняться этим?
Ни один из моих классов не имеет какого-либо подобия принудительной конфиденциальности, что-то никогда. Шаблон одноэлементности (ставящий под сомнение его достоинства) теперь невозможно обеспечить соблюдение. Как показывают мои фрагменты, даже некоторые базовые предположения о том, как основаны на Java, даже не гарантируются.
ЭТИ ПРОБЛЕМЫ НЕ РЕАЛЬНЫ???
Хорошо, я только что подтвердил: благодаря setAccessible
строки Java НЕ являются неизменными.
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!"
}
}
Я единственный, кто считает, что это ОГРОМНАЯ забота?