网络序列化数据更新后无法传输的问题排查
问题诊断与解决方案
核心问题:Java对象序列化的引用缓存机制
你的问题根源在于Java ObjectOutputStream的对象引用缓存特性:
- 首次调用
writeObject(serialTableData)时,JVM会缓存该ArrayList对象的引用及内容 - 后续修改数据后,你虽然重新创建了ArrayList,但如果其中的
MHSCalendarEntry是原有对象(仅修改内部属性),ObjectOutputStream会直接发送缓存的旧对象引用,而非新内容 - 测试代码绕开原有变量,每次都生成全新对象链,因此能正常发送更新数据
验证点
确认MHSCalendarEntry类的使用场景:
- 是否直接修改已有实例的内部属性,而非创建新实例替换进
tableData - 是否实现
Serializable但未重写序列化方法,也未用transient标记可变属性
解决方案
方案1:清除序列化缓存
每次发送前调用reset()清空ObjectOutputStream的引用缓存:
public boolean saveToFile() { try { serialTableData = new ArrayList<>(tableData); System.out.println("Sending calendar:\n" + MHSCalendarEntry.toString(serialTableData)); heartbeatProxy.reset(); // 新增:清除缓存,强制序列化新内容 heartbeatProxy.writeObject(serialTableData); return true; } catch (IOException ex) { alert(); return false; } }
方案2:创建全新数据实例
修改数据时,不直接修改原有MHSCalendarEntry属性,而是生成新实例替换:
// 示例修改逻辑 MHSCalendarEntry oldEntry = tableData.get(targetIndex); // 用更新后的属性创建新实例 MHSCalendarEntry newEntry = new MHSCalendarEntry(oldEntry.getId(), updatedShift, updatedDate); tableData.set(targetIndex, newEntry);
方案3:自定义序列化逻辑
在MHSCalendarEntry中重写序列化方法,强制写入最新属性:
private void writeObject(ObjectOutputStream out) throws IOException { // 手动写入所有需要序列化的属性 out.writeInt(this.entryId); out.writeUTF(this.shiftType); out.writeObject(this.workDate); // 其他属性依次写入 } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { // 对应读取属性 this.entryId = in.readInt(); this.shiftType = in.readUTF(); this.workDate = (LocalDate) in.readObject(); // 其他属性依次读取 }
测试代码正常的原因
测试代码绕开原有变量,每次都生成全新的对象(包括MHSCalendarEntry实例),ObjectOutputStream会将其视为新引用处理,不会触发缓存,因此服务器能接收更新后的数据。
内容的提问来源于stack exchange,提问作者cworner1
相关产品推荐
相关产品推荐

