阿里云开发者 2024年10月01日
我的字段被FastJson给干掉了?!
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文记录作者升级到 JDK 11 后遇到的 FastJSON 序列化问题,以及详细的排查过程。作者通过回滚、排查端口、日志分析等方式逐步定位问题,最终发现是由于二方库中遗漏了 `Money` 类中的 `setAmount` 方法导致的。作者还分享了排查过程中的经验教训,例如要重视多端测试,以及对业务异常进行监控等。

🤔 作者遇到了 FastJSON 序列化问题,导致订单页面无法发起纠纷。

🐛 排查过程曲折,从端口问题、健康检查、日志分析、二方库版本升级等多个方面入手,最终定位到问题根源:二方库中 `Money` 类遗漏了 `setAmount` 方法。

💡 作者总结了几个经验教训: 1. 多端测试的重要性:不要只测试 PC 端,也要测试 APP 端。 2. 对业务异常进行监控:即使是业务校验异常,也要进行监控,如果出现大批量上涨,也要引起重视。 3. 要注意二方库的版本问题:升级二方库时要仔细测试,确保新版本兼容性良好。

📚 作者也分享了 FastJSON 相关知识,例如 ASM 的作用、ClassLoader 的机制、FastJSON2 的优势等。

原创 河影 2024-09-09 08:31 浙江

升级到 JDK 11 后遇到的 FastJSON 序列化问题,以及详细的排查过程。

阿里妹导读


本文记录作者升级到 JDK 11 后遇到的 FastJSON 序列化问题,以及详细的排查过程。

0. 写在前面的省流版

升级到JDK 11后,类加载顺序有所改动,同名的类在多个jar中,导致实际加载的类不一样,因此序列化的结果不一样。

1. 现象

@客户服务(CCO) 出现批量买家反馈,现在订单页面无法发起纠纷,申请后就报错。辛苦帮忙看下。

2. 解决过程

3. 问题排查


机器不在线

问题现象:

排查过程:

new SpringApplicationBuilder(DestinyApplication.class)    .web(WebApplicationType.NONE)  // 指定应用不是 Web 应用    .profiles(DiamondProfiles.load())    .run(args);

@Controller    public static class OkController {
       @ResponseBody        @RequestMapping("/ok.jsp")        public String ok() {            return "success";        }
       /**         * 健康检查,系统部署需要         * 请不要删除!!         */        @GetMapping("/checkpreload.htm")        public @ResponseBody String checkPreload() {            return "success";        }
   }
icbusession.authorization.exclude-paths=/favicon.ico,/checkpreload.htm,/status.taobao,/ok.jsp


FastJson解析问题

问题复现

{"oldPostIssueRequestDTO":{"authorizedViewCommunication":false,"businessType":"XXX","buyerInfo":{"email":"cxw20180809@126.com"},"destinyTraceId":"XXX-84ba-68ad2b62690c","device":"IOS","issueReasonId":1022,"memo":"qqq","operation":"abortOrder","operatorAccountId":XXX,"operatorAliMemberId":CCC,"operatorType":"buyer","orderId":"XXX","payerList":[{"availableTaxAmount":{"amount":0.00,"cent":0,"centFactor":100,"currency":"USD","currencyCode":"USD"},"cardTailNo":"5164","currency":"USD","finNumber":["XXX"],"forexRefundAmount":{"amount":0.30,"cent":30,"centFactor":100,"currency":"USD","currencyCode":"USD"},"fundAmount"{"amount":0.00,"cent":0,"centFactor":100,"currency":"USD","currencyCode":"USD"},"online":true,"originPayMethod":"CREDIT_CARD_PAY","payContractId":"CCC","payGmtCreate":1724210447000,"payGmtCreateStr":"2024-08-20 20:20","payMethod":"CREDIT_CARD_PAY","payProcessFeeAmount":{"amount":0.01,"cent":1,"centFactor":100,"currency":"USD","currencyCode":"USD"},"payStep":"ADVANCE","payerName":"null null","rate":1,"refundAmount":{"amount":0.30,"cent":30,"centFactor":100,"currency":"USD","currencyCode":"USD"},"taxAmount":{"amount":0.00,"cent":0,"centFactor":100,"currency":"USD","currencyCode":"USD"},"termFundArrived":false}],"refundAmount":{"amount":0.00,"cent":0,"centFactor":100,"currency":"USD","currencyCode":"USD"}}}

fun parsePostIssueRequestDTO(request: String): PostIssueRequestDTO? {  var postIssueRequestDTO: PostIssueRequestDTO? = null  try {    postIssueRequestDTO = JSON.parseObject(request, PostIssueRequestDTO::class.java)  } catch (e: Throwable) {    logger.error("MtopIssueViewService.parsePostIssueRequestDTO parse request error.$request", e)  }
 if (postIssueRequestDTO == null) {    logger.error("MtopIssueViewService.parsePostIssueRequestDTO provideEvidenceForm is null.$request")  }
 return postIssueRequestDTO}

本地复现

<dependency>    <groupId>com.alibaba</groupId>    <artifactId>fastjson</artifactId>    <version>1.2.68.noneautotype</version></dependency>

改动范围review

依赖二方库的改动

JDK11的改动

仔细review前端传的字符串

Money类分析

public class Money implements Serializable, Comparable {    /**     * Comment for <code>serialVersionUID</code>     */    private static final long  serialVersionUID      = 6009335074727417445L;
   /**     * 缺省的币种代码,为CNY(人民币)。     */    public static final String DEFAULT_CURRENCY_CODE = "CNY";
   /**     * 缺省的取整模式,为<code>BigDecimal.ROUND_HALF_EVEN     * (四舍五入,当小数为0.5时,则取最近的偶数)。     */    public static final int    DEFAULT_ROUNDING_MODE = BigDecimal.ROUND_HALF_EVEN;
   /**     * 一组可能的元/分换算比例。     * <p>     * 此处,“分”是指货币的最小单位,“元”是货币的最常用单位, 不同的币种有不同的元/分换算比例,如人民币是100,而日元为1。     */    private static final int[] centFactors           = new int[] { 1, 10, 100, 1000 };
   /**     * 金额,以分为单位。     */    private long               cent;
   /**     * 币种。     */    private Currency currency;
   /**     * 币种代码     */    private String             currencyCode;}
// Bean方法 ====================================================
   /**     * 获取本货币对象代表的金额数。     *     * @return 金额数,以元为单位。     */    public BigDecimal getAmount() {        return BigDecimal.valueOf(cent, currency.getDefaultFractionDigits());    }
   /**     * 设置本货币对象代表的金额数。     *     * @param amount 金额数,以元为单位。     */    public void setAmount(BigDecimal amount) {        if (amount != null) {            cent = rounding(amount.movePointRight(2), BigDecimal.ROUND_HALF_EVEN);        }    }

FastJson分析

<dependency>    <groupId>com.alibaba.fastjson2</groupId>    <artifactId>fastjson2</artifactId>    <version>2.0.52</version></dependency>

FastJson代码探究

首先怀疑是ASM的问题

然后怀疑ClassLoader的问题

BeanInfo问题

终见端倪

真相大白

4. 总结

快速部署定制化文生图应用


PAI Stable Diffusion WebUI 解决方案为企业提供云上快速部署定制化的文生图应用。提供了方便、高效的模型部署产品,并支持根据实际需求,配置不同的服务版本及服务参数。具有分钟级部署上线,方便快捷、开箱即用,多版本部署方案,参数可定制化调整的优势。


点击阅读原文查看详情。

阅读原文

跳转微信打开

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

FastJSON 序列化 问题排查 JDK11 二方库 Money
相关文章