Чтобы исправить это, мы можем взять снимок ключей системных свойств:
final Properties systemProperties = System.getProperties()
final Set<String> keys = systemProperties.stringPropertyNames()
for (final String key : keys) {
System.out.println("key: " + key)
final String value = systemProperties.getProperty(key)
System.out.println("value: " + value) // value can be null!
}
Обратите внимание на комментарий value
- пока stringPropertyNames
сообщает set of keys in this property list where the key and its corresponding value are strings
, системасвойство могло быть изменено за это время.
Почему так много работы?
Системные свойства являются экземпляром java.util.Properties
, а его методы getProperty
, setProperty
Потоково-безопасный.
К сожалению, итератор набора записей Properties (который я использовал в вопросе) не является поточно-ориентированным:
Если карта изменяется во время итерации поset выполняется (кроме как через собственную операцию удаления итератора или через операцию setValue для записи карты, возвращаемой итератором), результаты итерации не определены
Так что на самом деле, когда я перебирална этой карте было изменено какое-то системное свойство (= эта запись была изменена), что вызвало выброс CME.
Эта пара вопросов и ответов также применима к любому общему использованию Properties
- только системные свойства делаютЭто сложнее, с возможностью доступа к ним напрямую с помощью статики, такой как java.lang.System.setProperty(String, String)
, поэтому управление всеми доступами (особенно в разделяемом коде) становится сложнее.