Java中fail-fast机制不直接作用于Fastjson的JSONObject,因其非标准集合类、无modCount字段及fail-fast校验逻辑;其迭代行为取决于底层Map类型(如HashMap则间接具备fail-fast能力,ConcurrentHashMap则为fail-safe)。

Java 中的 fail-fast 机制本身不作用于 Fastjson 的 JSONObject 迭代过程,因为 JSONObject(来自 Alibaba Fastjson)*不是标准 Java 集合框架(`java.util.)的实现类**,它不继承AbstractCollection或AbstractList,也不维护modCount字段,更不使用Iterator` 的 fail-fast 检查逻辑。
换句话说:
✅ ArrayList.iterator()、HashMap.entrySet().iterator() 等会触发 ConcurrentModificationException,是因其实现了标准 fail-fast 协议;
❌ JSONObject 的 keySet()、entrySet() 或 forEach() 遍历默认不带 fail-fast 行为——它不会在遍历时检测并发修改,也不会抛出 ConcurrentModificationException。
为什么 JSONObject 不触发 fail-fast?
Fastjson 的 JSONObject 本质是一个 HashMap<String, Object> 的包装类(v1.x)或基于 LinkedHashMap 的扩展(v2.x),但它的迭代器并未重写或继承标准集合的 Itr 类。其 keySet() 返回的是底层 map 的 keySet 视图,而该视图的迭代器行为取决于底层 map:
- 若底层是
HashMap(非线程安全),其keySet().iterator()是 fail-fast 的 → 此时可能抛ConcurrentModificationException; - 若底层是
ConcurrentHashMap(如某些自定义构造),则迭代器是弱一致性(fail-safe),不会抛该异常; - Fastjson v1 默认用
HashMap;v2 默认用LinkedHashMap,二者均属java.util包,其迭代器继承 AbstractMap 的 fail-fast 实现 → 所以间接具备 fail-fast 能力。
⚠️ 关键点:
JSONObject自身不控制迭代器逻辑,真正起作用的是它内部持有的 Map 实例类型及其迭代器实现。立即学习“Java免费学习笔记(深入)”;
常见场景与风险
场景1:单线程中边遍历边修改 JSONObject
JSONObject obj = new JSONObject();
obj.put("a", 1);
obj.put("b", 2);
for (String key : obj.keySet()) {
if ("a".equals(key)) {
obj.remove("b"); // ⚠️ 可能触发 ConcurrentModificationException
}
}→ 实际是否抛异常,取决于 obj 底层 map 类型及 JDK 版本。HashMap 在 JDK 8+ 中,keySet().iterator() 的 next() 方法会在每次调用时检查 modCount,删除操作会改变 modCount,导致下一次 hasNext() 或 next() 抛异常。
场景2:多线程读写 JSONObject
- 多个线程同时调用
obj.put()/obj.remove()+obj.forEach(...) -
HashMap非线程安全 → 除ConcurrentModificationException外,还可能引发死循环(JDK 7)、数据丢失、NullPointerException等未定义行为 - 这不是 fail-fast 的“保护”,而是底层 map 的并发缺陷。
如何安全迭代并修改?
| 目标 | 推荐方式 |
|---|---|
| 单线程安全修改 | 使用 Iterator.remove()(如果底层 map 支持)java<br>Iterator<String> it = obj.keySet().iterator();<br>while (it.hasNext()) {<br> String k = it.next();<br> if ("a".equals(k)) it.remove(); // ✅ 安全<br>}<br>
|
| 避免 CME 异常 | 先收集待删 key,遍历结束后统一删:java<br>List<String> toRemove = new ArrayList<>();<br>for (String k : obj.keySet()) {<br> if (needRemove(k)) toRemove.add(k);<br>}<br>toRemove.forEach(obj::remove);<br>
|
| 多线程环境 | 不要用 JSONObject 做共享可变状态✅ 改用线程安全容器(如 ConcurrentHashMap)✅ 或用 CopyOnWriteArrayList 存储 JSON 对象✅ 或加 synchronized 锁住整个 JSONObject 实例 |
注意:Fastjson 本身不是线程安全的序列化/反序列化工具(尤其 v1.x),
JSONObject实例也不承诺线程安全。共享可变JSONObject是设计隐患,应尽量避免。
Fastjson v2 的变化(补充)
Fastjson2(com.alibaba.fastjson2.JSONObject)改用不可变/线程友好的设计倾向:
- 默认构造器创建的是
LinkedHashMap实例(仍 fail-fast); - 提供
JSONFactory可指定底层 map 类型; - 明确文档指出:
JSONObject实例不保证线程安全,多线程并发读写需外部同步。
所以,无论 v1 还是 v2,不要依赖 JSONObject 的迭代器做并发防护,它没有内置 fail-fast 校验逻辑,也不提供线程安全保障。
本质上,所谓“Fastjson 校验 JSONObject 迭代时的并发修改”,并不是一个由 fail-fast 主动拦截的过程,而往往是底层 map 暴露的并发缺陷所引发的副作用。真正要解决的,是数据结构选型 + 访问控制 + 线程协作规范,而非等待某个异常来“提醒”。


















