You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java:Socket二次写入后HashMap值未更新问题排查

嘿,这个问题我太熟悉了——这是Java对象序列化的默认缓存机制在搞鬼!

问题根源

当你用ObjectOutputStream.writeObject()写入同一个对象引用时,第一次序列化会把完整的对象数据写入流,同时把这个对象的引用缓存起来。后续再写同一个引用时,它只会发送一个“引用标记”,根本不会重新序列化对象的最新状态!

看你的客户端代码,循环里一直复用同一个updateCO对象,哪怕你修改了它内部的changes HashMap,ObjectOutputStream也不会重新序列化这个对象的最新状态——所以服务端拿到的永远是第一次序列化时的旧对象,自然看不到Id的更新。


解决办法(按简单程度排序)

1. 写入前重置流(最快捷)

在每次调用writeObject()之前,加一行objectOutputStream.reset(),它会清空流的对象缓存,强制重新序列化当前对象的最新状态:

while(true){
    i++;
    changes.put("Id",""+i);
    objectOutputStream.reset(); // 关键新增代码
    objectOutputStream.writeObject(updateCO);
    objectInputStream.readObject();
    changes.put("username","3");
    System.out.println(changes.get("Id"));
    if(i>50) break;
}

2. 每次循环新建对象(最稳妥,无缓存问题)

如果场景允许,每次循环都创建新的UpdateContextObject实例,这样每次写入的都是全新的对象引用,流会完整序列化最新内容:

while(true){
    i++;
    UpdateContextObject updateCO = new UpdateContextObject();
    updateCO.setTable("users");
    updateCO.setAttributes(new HashMap<>());
    Map<String,String> changes = new HashMap<>();
    changes.put("Id",""+i);
    changes.put("username","3");
    updateCO.setChanges(changes);
    
    objectOutputStream.writeObject(updateCO);
    objectInputStream.readObject();
    System.out.println(changes.get("Id"));
    if(i>50) break;
}

3. 使用writeUnshared()替代writeObject()

这个方法会绕过对象缓存,每次都序列化当前对象的状态(注意:如果对象内部还有共享的嵌套对象,可能需要额外处理嵌套对象的序列化):

objectOutputStream.writeUnshared(updateCO);

4. 自定义序列化逻辑(进阶)

让UpdateContextObject实现Externalizable接口,自己编写writeExternal()和readExternal()方法,手动控制序列化过程,确保每次都写入最新的HashMap数据。这个方法适合需要高度自定义序列化的场景,相对复杂一些。


先试试第一种方法,改完就能看到服务端日志开始打印递增的Id值啦!

内容的提问来源于stack exchange,提问作者user2962142

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:37:16