ObjectMapper序列化时随机追加服务器时间串至JSON字段问题
问题原因及解决办法
可能的原因
- 多线程共享对象导致的数据篡改:如果
Root、RootNode或ToMatchInputDto的实例被多个线程同时访问和修改(比如作为全局变量、单例对象存在),线程间的并发写操作会破坏字符串的完整性,随机插入时间串。这种场景下,时间串通常是其他线程的日志或业务逻辑中生成的时间值,意外污染了当前对象的字段。 - 自定义序列化逻辑存在漏洞:如果项目中自定义了Jackson的
JsonSerializer或扩展了Jackson模块,代码中可能错误地将时间串插入到了序列化的键或值中,且逻辑存在随机性导致问题偶发。 - 字节码增强工具的干扰:APM监控工具(如SkyWalking、Pinpoint)、AOP切面或自定义Java Agent可能在运行时篡改实体类的字段或序列化流程,意外插入时间串。
- 不安全的字符串操作:赋值字段时使用了非线程安全的可变字符序列(如
StringBuilder)且被多线程共享,最终转成的String出现脏数据。
解决办法
1. 确保对象的线程封闭性
- 检查
rootObj及其内部嵌套对象的创建和使用逻辑,每个序列化操作使用独立的对象实例,避免将实体类实例作为全局变量或单例共享给多个线程。 - 在Web环境中,确保这些实体类是请求域内的局部对象,不会被多个请求线程同时修改。
2. 排查自定义序列化逻辑
- 检查项目中是否存在自定义的
JsonSerializer、Module或Jackson全局配置,确认没有代码错误地向序列化结果中插入时间串。 - 临时禁用自定义序列化逻辑,验证问题是否消失。
3. 排查第三方工具干扰
- 临时关闭APM监控、自定义AOP切面或Java Agent,观察问题是否重现,以此确认是否是字节码篡改导致的问题。
- 如果确认是第三方工具的问题,调整工具的配置,排除对目标实体类的增强操作。
4. 规范字符串操作
- 给实体类字段赋值时,优先使用不可变的
String类型;如果必须使用可变字符序列(如StringBuilder),确保每个线程使用独立的实例,或使用ThreadLocal封装可变对象。
验证步骤
- 编写单线程测试代码,重复序列化同一个对象,若问题不再出现,可确定是多线程共享对象导致的。
- 序列化前打印
rootObj.toString()(实体类已标注@ToString),如果打印结果中已经存在时间串,说明问题出在对象赋值阶段,而非Jackson序列化过程。
内容的提问来源于stack exchange,提问作者Dipanjan Baidya
相关产品推荐
相关产品推荐

