java - 非常奇怪 : android: java. util.logging.Logger.removeHandler 抛出 ConcurrentModificationException

标签 java android

注意!!!

您在发布的代码中看到的 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/

相关文章:

java - JBoss 6 中实例之间共享属性文件

android - 如何用RecycleView展示分层数据结构?

android - 如何在android中制作双搜索栏?

java - Maven:使用 JDK8 编译 Java 7

javascript - 如何保证数据库数据始终准确反射(reflect)在网页中?

java - 外部访问cloudbees中的Spring Java RMI服务

java - Android - 通过 Html.fromHtml TextView 中的图像?

android - 如何更改 NavigationView 中的标题高度?

android - buildConfigField 取决于 flavor + buildType

java - Android SQLite 查询在选择器中有问号,在 selectionArgs 中有空