非常奇怪:android:java.util.logging.Logger.removeHandler抛出ConcurrentModificationException 注意!!!
对于您在发布的代码中看到的每个迭代器,不会引发此异常 我在android应用程序中遇到了一个非常奇怪的ConcurrentModificationException非常奇怪:android:java.util.logging.Logger.removeHandler抛出ConcurrentModificationException 注意!!!,java,android,Java,Android,对于您在发布的代码中看到的每个迭代器,不会引发此异常 我在android应用程序中遇到了一个非常奇怪的ConcurrentModificationException import java.util.logging.Handler; import java.util.logging.Logger; public MyApp extends Application { private static final Logger rootLogger = Logger.getLogger("")
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)
注意!!!
对于您在发布的代码中看到的每个迭代器,不会引发此异常
Application.onCreate()
没有并发访问权限
以下是供您参考的源代码:
我强烈建议您阅读源代码,这必须有助于理解我下面解释的内容
===这就是我为例外情况所做的研究===
让我们转到这里Handler[]handlers=rootLogger.getHandlers()第一个代码块中的code>。Logger.getHandlers()的实现是:
public Handler[] getHandlers() {
return handlers.toArray(EMPTY_HANDLERS_ARRAY);
}
在Logger.java中,Logger.removeHandler(Handler)
的核心部分是:
private final List<Handler> handlers = new CopyOnWriteArrayList<Handler>();
public void removeHandler(Handler handler) {
......
this.handlers.remove(handler);
updateDalvikLogHandler();
}
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();
}
......
}
public E next(){
ArrayList ourList=ArrayList.this;
int rem=剩余;
if(ourList.modCount!=expectedModCount){
抛出新的ConcurrentModificationException();
}
......
}
异常的确切原因是调用(Logger-Logger:children)
时,在某个地方修改了Logger.children
java的评论说它的所有方法都是线程安全的
===我的解释结束,我的问题开始===
我完全搞不懂在中修改的Logger.children
。但是我的代码不调用LogManager
我相信我需要有人帮助我澄清我的想法,并帮助找到错误
非常感谢您阅读这篇长篇博文……我无法发表评论,因此我将发布这篇博文作为答案
如果您对每个代码的注释,是否会引发异常
我怀疑引发异常是因为您在代码的其他地方执行了logger=rootLogger
之后正在修改logger
,并且系统也在修改它。我无法发表评论,因此我会将此作为答案发布
如果您对每个代码的注释,是否会引发异常
我怀疑引发异常是因为您在代码的其他地方执行了logger=rootLogger
之后正在修改logger
,并且系统也在修改它。中:
您可能正在其他类中创建记录器,例如
static final LOG = Logger.getLogger(MyClass.class.getName())
从而更新Logger.children属性
这可以从主线程以外的其他线程调用。当您从其他线程使用MyClass时,静态字段初始化将创建新的记录器,该记录器将更新根记录器的子属性
在这种情况下,我认为使用日志属性不同步到LogMealgor。
解决方法是在同步块中调用日志初始化
synchronized (LogManager.getLogManager()) {
Handler[] handlers = rootLogger.getHandlers();
for (Handler handler : handlers) {
rootLogger.removeHandler(handler);
}
rootLogger.addHandler(rootHandler);
rootLogger.setLevel(fileLogLevel);
}
在:
您可能正在其他类中创建记录器,例如
static final LOG = Logger.getLogger(MyClass.class.getName())
从而更新Logger.children属性
这可以从主线程以外的其他线程调用。当您从其他线程使用MyClass时,静态字段初始化将创建新的记录器,该记录器将更新根记录器的子属性
在这种情况下,我认为使用日志属性不同步到LogMealgor。
解决方法是在同步块中调用日志初始化
synchronized (LogManager.getLogManager()) {
Handler[] handlers = rootLogger.getHandlers();
for (Handler handler : handlers) {
rootLogger.removeHandler(handler);
}
rootLogger.addHandler(rootHandler);
rootLogger.setLevel(fileLogLevel);
}
创建数组/列表的副本,如newarraylist(handlers)
。您不应该在遍历集合时将其从集合中删除。@JaredBurrows如果我发布的foreach没有引发异常,请阅读注释
。创建数组/列表的副本,如新建数组列表(处理程序)
。您不应该在遍历集合时将其从集合中删除。@JaredBurrows如果我发布的foreach没有引发异常,请阅读注释代码>rootLogger
仅在我发布的位置访问。。。我已经搜索了该项目。rootLogger
仅在我发布的地方被访问。。。我已经搜索了这个项目。