gson 替换 fastjson 引发的线上问题分析

本文讲述了将fastjson替换为gson后在线上出现的OOM问题,通过分析内存dump发现gson在序列化重复对象时未进行优化,导致报文体积过大。对比测试显示,gson的序列化压缩比和吞吐量均不如fastjson和其他框架。文章提醒开发者在选择序列化框架时需谨慎,考虑各种场景的适应性和性能表现。
摘要由CSDN通过智能技术生成

前言

Json 序列化框架存在的安全漏洞一直以来都是程序员们挂在嘴边调侃的一个话题,尤其是这两年 fastjson 由于被针对性研究,更是频频地的报出漏洞,出个漏洞不要紧,可安全团队总是用邮件催着线上应用要进行依赖升级,这可就要命了,我相信很多小伙伴也是不胜其苦,考虑了使用其他序列化框架替换 fastjson。这不,最近我们就有一个项目将 fastjson 替换为了 gson,引发了一个线上的问题。分享下这次的经历,以免大家踩到同样的坑,在此警示大家,规范千万条,安全第一条,升级不规范,线上两行泪。

问题描述

线上一个非常简单的逻辑,将对象序列化成 fastjson,再使用 HTTP 请求将字符串发送出去。原本工作的好好的,在将 fastjson 替换为 gson 之后,竟然引发了线上的 OOM。经过内存 dump 分析,发现竟然发送了一个 400 M+ 的报文,由于 HTTP 工具没有做发送大小的校验,强行进行了传输,直接导致了线上服务整体不可用。

问题分析

为什么同样是 Json 序列化,fastjson 没出过问题,而换成 gson 之后立马就暴露了呢?通过分析内存 dump 的数据,发现很多字段的值都是重复的,再结合我们业务数据的特点,一下子定位到了问题 – gson 序列化重复对象存在严重的缺陷。

直接用一个简单的例子,来说明当时的问题。模拟线上的数据特性,使用 List<Foo> 添加进同一个引用对象

Foo foo = new Foo();
Bar bar = new Bar();
List<Foo> foos = new ArrayList<>();
for(int i=0;i<3;i++){
    foos.add(foo);
}
bar.setFoos(foos);

Gson gson = new Gson();
String gsonStr = gson.toJson(bar);
System.out.println(gsonStr);

String fastjsonStr = JSON.toJSONString(bar);
System.out.println(fastjsonStr); 

观察打印结果:

gson:

{"foos":[{"a":"aaaaa"},{"a":"aaaaa"},{"a":"aaaaa"}]} 

fastjson:

{"foos":[{"a":"aaaaa"},{"$ref":"$.foos[0]"},{"$ref":"$.foos[0]"}]} 

可以发现 gson 处理重复对象,是对每个对象都进行了序列化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值