由于在某些环境中重新启动JVM之后得到System.getProperties()
,我无法使用java.util.ConcurrentModificationException
读取JVM配置属性。
[err] java.util.ConcurrentModificationException [err] at java.util.Hashtable $ Enumerator.next(Hashtable.java:1502)
我必须多次重启VM,以避免前面提到的错误。
我到目前为止所做的:
由于线程安全,我正在使用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] at com.myapp.input.ConfigurationServer.parse(ConfigurationServer.java:710) [err] at com.myapp.input.ConfigurationServer.configure(ConfigurationServer.java:94) com.myapp.input.Application.run(Application.java:78)的[err] com.myapp.input.servlet.InputStarter $ ValidatorThread.run(InputStarter.java:113)
此致
PS:我应该添加同步块来调用该方法吗? 例如:在parse方法中,应使用
调用我的代码synchronized(this) {
PropertyLogger.logProperties();
}
答案 0 :(得分:1)
问题不在于日志记录框架,而是行
shared.putAll(props);
Properties
类扩展了Hashtable
,并且系统属性可以随时更改。使用shared.putAll(props)
遍历props
类的对象Properties(Hashtable)
,如果在迭代过程中修改了任何值,我们将得到此错误ConcurrentModificationException
一种解决方案是在迭代之前在System.Properties()对象上调用clone()