Ответ 1
Оба метода имеют различный смысл, и, следовательно, правильный должен использоваться в зависимости от того, что должен делать текущий код.
Код System.getProperty("property")
говорит: "Дайте мне значение свойства, если текущий контекст безопасности позволяет мне его прочитать".
Код, который использует doPrivileged
, говорит: "Дайте мне значение свойства, если текущий класс (где находится эта строка кода) разрешен для чтения".
Разница вступает в игру, когда домен защиты текущего класса отличается от текущего активного контекста безопасности.
Например, рассмотрим фреймворк, который выполняет код плагина, который не доверен. Таким образом, среда использует SecurityManager для ограничения действий ненадежного кода плагина. Но, конечно, плагин может вызывать некоторые методы фреймворка и предположить, что один из этих методов должен прочитать свойство. Теперь, когда метод вызывается из ненадежного ограниченного кода, он сам ограничен и, таким образом, считывание свойства завершится неудачно. Но, конечно, структура доверяет себе и хочет, чтобы она могла читать это свойство, даже в том случае, если где-то в стеке вызовов есть ненадежный код. Это, когда вам нужно использовать doPrivileged
. В основном он говорит "независимо от того, что там в стеке вызовов, я часть кода рамки, и мне разрешено делать все, что разрешено для кода структуры". Поэтому чтение свойства с использованием второго метода завершается успешно.
Конечно, при использовании doPrivileged
нужно быть осторожным, чтобы не допустить (ненадежный) код вызова. Если, например, код рамки предлагает следующий метод плагину:
public String getProp(String key) {
return (String) java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction(key));
}
это полностью аннулирует политику, которой недоверенному коду не разрешено читать системные свойства, потому что он может просто использовать ваш метод.
Поэтому используйте этот метод только тогда, когда вы знаете, что это безопасно, и только тогда, когда вам это нужно (то есть, когда вы хотите, чтобы ваш код мог делать больше, чем какой-либо другой код, должен иметь возможность делать это напрямую), Внутри обычного приложения (которое обычно выполняется без SecurityManager или одного и того же контекста безопасности для всего кода), нет никакой разницы, и следует использовать первый метод.