一度異常JSONObject toStringが発生した同時修正異常C o n c u r r e ntModificationExceptionを記録する
3854 ワード
シーンの説明
データを報告するコンポーネントを作る時、jsonObjectオブジェクトを一つの方法のパラメータとして、外層から入ってきて、このオブジェクトを操作するスレッドは複数あるかもしれない、例えば:報告スレッド、バックアップスレッドなど、そしてデータ量が大きい時、偶発的に合併して異常を修正して、よくjsonObjectで発見する.TOString()のとき.異常
08-13 15:10:54.207 16625-16709/com..xxx E/Tinker.UncaughtHandler: TinkerUncaughtHandler catch exception:java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:346)
at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:375)
at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:373)
at org.json.JSONObject.writeTo(JSONObject.java:719)
at org.json.JSONStringer.value(JSONStringer.java:237)
at org.json.JSONObject.writeTo(JSONObject.java:720)
at org.json.JSONStringer.value(JSONStringer.java:237)
at org.json.JSONArray.writeTo(JSONArray.java:613)
at org.json.JSONArray.toString(JSONArray.java:585)
at com.xxx.xxx.report.thread.CommonBackupThread.innerBackup(CommonBackupThread.java:36)
at com.xxx.xxx.report.thread.CommonBackupThread.access$000(CommonBackupThread.java:22)
at com.xxx.xxx.report.thread.CommonBackupThread$1.run(CommonBackupThread.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
以上から,JSOnArrayオブジェクトのtoString()メソッドを呼び出す際に,同時修正異常を投げ出したことが分かる.
もんだいぶんせき
同時修正異常とは何か一般的によく知られていますが、多くのシーンは集合の操作に現れます.反復しながら集合を修正すると、同時修正異常が発生しやすくなります.
たとえば、次の例では、同時変更例外が発生します.
);
list.add(2);
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Integer s = iterator.next();
if (s == 2) {
list.remove(s);
}
}
同時異常を放出する具体的なコード分析については、次の項目を参照してください.https://www.cnblogs.com/bsjl/p/7676209.html
なぜjsonObjectまたはjsonArray toStringが異常を投げ出すのかを主に分析するまずjsonObjectのtoString法を見る
@Override public String toString() {
try {
JSONStringer stringer = new JSONStringer();
writeTo(stringer);
return stringer.toString();
} catch (JSONException e) {
return null;
}
}
writeToメソッドに入ると、mapセット
nameValuePairs
の遍歴が見られます void writeTo(JSONStringer stringer) throws JSONException {
stringer.object();
for (Map.Entry entry : nameValuePairs.entrySet()) {
stringer.key(entry.getKey()).value(entry.getValue());
}
stringer.endObject();
}
そして私たちがjsonObjectのようにデータを詰め込んだときはこうでした
public JSONObject put(String name, boolean value) throws JSONException {
nameValuePairs.put(checkName(name), value);
return this;
}
ここで結論を見ると,toStringには呼び出し集合の高度なforループ(下位反復器で実現される)があり,データを追加する際に直接集合を操作し,読み書きが同じスレッドにないため,自然と問題が発生しやすい.
異常発生原因の回顧