1. 事故背景与问题复现
那天晚上11点23分,我正准备上线一个简单的国家信息查询功能。这个功能的核心代码不到50行,就是从一个DTO对象中提取国家名称并返回JSON格式数据。在最后一次代码review时,我鬼使神差地加了一行日志:
java复制log.info("国家信息查询请求: {}", countryDTO);
就是这行看似无害的日志,上线后立即触发了大量空指针异常报警。我们紧急回滚后排查发现,问题出在CountryDTO类的isChinaName()方法上。这个案例完美诠释了什么叫"一行代码引发的血案"。
让我们先还原这个DTO的结构:
java复制public class CountryDTO {
private String country;
public void setCountry(String country) {
this.country = country;
}
public String getCountry() {
return this.country;
}
public Boolean isChinaName() {
return this.country.equals("中国"); // 问题根源
}
}
当country为null时,调用equals方法自然会抛出NPE。但奇怪的是,我们明明只是做了JSON序列化,为什么会执行isChinaName()方法呢?
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. FastJson序列化机制深度解析
2.1 序列化执行流程揭秘
通过Debug堆栈信息,我们发现FastJson在序列化过程中动态生成了一个ASMSerializer_1_CountryDTO类。这是FastJson使用ASM技术实现的性能优化 - 通过动态生成字节码来避免反射开销。
核心流程是这样的:
- 调用JSON.toJSONString()时,FastJson会通过SerializeConfig获取适合的序列化器
- 对于普通JavaBean,会创建JavaBeanSerializer
- 在序列化过程中,会调用对象的getter方法获取属性值
关键
