У меня проблемы с чтением свойств конфигурации JVM с System.getProperties()
из-за того, что в некоторых средах я получаю java.util.ConcurrentModificationException
после перезапуска JVM.
[err] java.util.ConcurrentModificationException [err] в java.util.Hashtable $ Enumerator.next (Hashtable.java:1502)
Мне нужно перезапуститьнесколько раз VM, чтобы избежать ранее упомянутой ошибки.
Что я делал до сих пор:
- синхронизировал метод, где ключи свойств и значения читаются и записываются в файл журнала;
- , поскольку объект свойств Java является HashMap, я пытался использовать синхронизированную карту;
- Я пытался смоделировать проблему параллелизма, используя больше потоков, которые совместно используют один и тот же объект свойств, однако у меня естьне удалось воспроизвести ошибку в моем локальном окружении;
Я использую StringBuffer из-за того, что он потокобезопасен;
private static final Logger LOG = LoggerFactory.getLogger(PropertyLogger.class);
public static synchronized final void logProperties() {
Level oldLevel = LOG.getLevel();
LOG.setLevel(Level.INFO);
Properties props = System.getProperties();
Map<Object, Object> shared = Collections.synchronizedMap(new HashMap<>());
shared.putAll(props);
for (final Entry<Object, Object> entry : shared.entrySet()) {
try{ StringBuffer buffer = new StringBuffer();
buffer.append(entry.getKey());
buffer.append(" = "); //$NON-NLS-1$
buffer.append(entry.getValue());
LOG.info(buffer.toString());
}
catch (Exception ex){
ex.printStackTrace();
}
}
LOG.setLevel(oldLevel);
}
Возможно, проблемы, с которыми я сталкиваюсь, запускаются также библиотекой log4j, используемой для записи, которая, насколько я знаю, не безопасна для потоков.
Я добавил трассировку стека:
[err] java.util.ConcurrentModificationException [err] в java.util.Hashtable $ Enumerator.next (Hashtable.java:1502) [err] в com.myapp.common.PropertyLogger.logProperties (PropertyLogger.java: 23) [err] в com.myapp.input.ConfigurationServer.parse (ConfigurationServer.java:710) [err] в com.myapp.input.ConfigurationServer.configure (ConfigurationServer.java:94) [err] в com.myapp.input.Application.run (Application.java:78) [err] at com.myapp.input.servlet.InputStarter $ ValidatorThread.run (InputStarter.java:113)
С уважением,
PS: Должен ли я добавить синхронизированные блоки для вызова метода?Например: метод parse должен вызывать мой код с
synchronized(this) {
PropertyLogger.logProperties();
}