注意!!!
您在发布的代码中看到的 for-each 迭代器不会抛出此异常!!!
我在我的 Android 应用程序中遇到了一个非常奇怪的 ConcurrentModificationException。
import java.util.logging.Handler;
import java.util.logging.Logger;
public MyApp extends Application {
private static final Logger rootLogger = Logger.getLogger("");
@override
public void onCreate() {
super.onCreate();
......
Handler[] handlers = rootLogger.getHandlers();
for (Handler handler : handlers) {
rootLogger.removeHandler(handler);
}
rootLogger.addHandler(rootHandler);
rootLogger.setLevel(fileLogLevel);
}
}
在极少数情况下,当我通过单击桌面图标启动应用程序时,会出现异常:
Caused by: java.util.ConcurrentModificationException
E/AndroidRuntime(26111): at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)
E/AndroidRuntime(26111): at java.util.logging.Logger.updateDalvikLogHandler(Logger.java:232)
E/AndroidRuntime(26111): at java.util.logging.Logger.updateDalvikLogHandler(Logger.java:233)
E/AndroidRuntime(26111): at java.util.logging.Logger.removeHandler(Logger.java:486)
注意!!!
您在发布的代码中看到的 for-each 迭代器不会抛出此异常!!!
Application.onCreate()
没有并发访问。
这里是源代码供您引用:https://android.googlesource.com/platform/libcore/+/android-6.0.1_r54/luni/src/main/java/java/util/logging/ .
我强烈建议您阅读源代码,这必须有助于理解我下面解释的内容。
===这是我研究的异常===
让我们进入第一个代码块中的Handler[] handlers = rootLogger.getHandlers();
。 Logger.getHandlers()
的实现是:
public Handler[] getHandlers() {
return handlers.toArray(EMPTY_HANDLERS_ARRAY);
}
而Logger.removeHandler(Handler)
的核心部分是在Logger.java中:
private final List<Handler> handlers = new CopyOnWriteArrayList<Handler>();
public void removeHandler(Handler handler) {
......
this.handlers.remove(handler);
updateDalvikLogHandler();
}
因此我们可以看到,第一个代码块中发布的 logger.removeHandler(handler);
并未引发异常。
让我们深入研究异常跟踪。异常(exception)是在 Logger.java:
for (Logger logger : children) { // this line in crash trace
logger.updateDalvikLogHandler();
}
这是 ArrayList.java 中异常跟踪的最后一个条目:
public E next() {
ArrayList<E> ourList = ArrayList.this;
int rem = remaining;
if (ourList.modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
......
}
异常的确切原因是调用for (Logger logger : Children)
时,Logger.children
在某处被修改。
Logger.java 的注释说它的所有方法都是线程安全的。
===我的解释结束,我的问题开始===
我完全困惑 Logger.children
发生了什么,它在 https://android.googlesource.com/platform/libcore/+/android-6.0.1_r54/luni/src/main/java/java/util/logging/LogManager.java 中进行了修改。但我的代码没有调用 LogManager
。
我相信我需要有人帮助我澄清我的想法,并帮助我找到错误。
非常感谢您阅读这篇长文...
最佳答案
我无法发表评论,因此我会将其作为答案发布。
如果对for-each代码进行注释,是否会抛出异常?
我怀疑抛出异常是因为您在代码中的其他地方执行了 logger = rootLogger
之后修改了 logger
,并且系统也在修改它。
关于java - 非常奇怪 : android: java. util.logging.Logger.removeHandler 抛出 ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38262189/