Fastjson 很快,但不适合我....
Posted Java技术栈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Fastjson 很快,但不适合我....相关的知识,希望对你有一定的参考价值。
作者:nyingping
来源:juejin.cn/post/7215886869199863869
记者:大爷您有什么特长呀?
FastJson:我很快。
记者:23423 乘以 4534 等于多少?
FastJson:等于 2343.
记者:??
FastJson:你就说快不快吧!
这个略显马丽苏的标题,各位看官将就着看吧。主要是怕被喷。FastJson 真的很好,我用不用我喜不喜欢的,太不重要了,我只是觉得不适合我而已。
话说以前 Gson 用得好好的,同事极力推荐我使用 FastJson,说很快云云。尽管我们的系统根本感知不出来这点速度差异。
之前也听说 FastJson 爆出来什么重大漏洞,但对我们基本没什么影响,所以这一点倒是没什么偏见。
然后在一个新项目上,脑抽抽,把 Gson 换成了 FastJson,Spring Boot 默认支持的 Jackson 换成了 FastJson。
然后就开始遇到了一些问题。先声明,这真不是尬黑,为了文章效果,故意网上扒些黑料拼凑起来,本文所提到的问题,都来源于本人最近项目的真实经历。
推荐一个开源免费的 Spring Boot 最全教程:
dateformat 优先级
本来是一个风和日丽的下午,一个非常简单的改动需求。接口返回的时间只需要年月日日期类型不需要时分秒。因为我配置全局时间格式化为yyyy-MM-dd HH:mmss
,于是我愉快的在 javabean 的属性上加了个注解。
本地测试一下,没问题,提交到测试环境,搞定,完美。
然后就接到产品的疑问,改动呢?
我登上去看了一下,唉,没改到啊,日期还是带了时分秒。我大意了啊,这么小的改动,又是在测试环境,就没加验证。
那么现在的直接问题是:FastJson 关于时间配置在局部的配置没有生效,使用的还是全局配置。
现象是,开发环境 Windows 上没有问题,测试环境 Linux 上出现了问题。两者有什么区别呢?系统问题?
既然怀疑是两个系统导致的问题,那么就在 idea 里模拟一下 linux 系统。在 VM options 添加 -Dos.name=linux
这不能完全模拟 linux 系统,只针对通过
System.getproperty("os.name")
来判断当前系统做某些操作的时候有用。
通过这种方式没复现,我又想到了远程调试。
一阵操作猛如虎,远程调试倒是能进断点,只是断点进不了第三方 jar 包的源码。等于白搞。
得,还是回到源码吧。拉下源码,断点,观察 JSONSerializer
类,主要是writeWithFormat
方法。没有发现问题。
因为怀疑是系统导致的,在源码中搜索\'linux\'\'unix\'关键字,没有发现。断点整个流程重点观察了一下这部份也没有发现问题。
突然在 JSONSerializer.dateFormatPattern
上发现了这段注释。
这部份涉及到了调整 dateformat 的问题,重点在这个#1868
,这通常是 github 的问题编号。
1.对于开源项目来说,解决了 BUG,通常会把问题编号放到注释里面去。前提是注释有必要。通过问题编号可以看到问题的前因后果。
2.通常来说,对于 github 开源项目都有 issue 区,拿着这个到编号直接到 issue 一搜就能搜到。
3.但也有一些项级项目,如 spark,flink 是没有 issue 区的,它们的类型问题发现描述追踪都使用 jira 平台。如:
https://issues.apache.org/jira/browse/SPARK-38349
在提交 PR 的时候标题也严格按照
[jira 编号][spark 子模块(如core/sql) title]
的规则来。
所以拿着这个编号到issue
区,不管有没有issue
区,也都可以直接到pullrequest
区直接搜索,就算 PR 标题里没有问题编号,PR 描述肯定也是有的,只要是有严格 PR 流程的开源项目。
所以这个问题在这里:
相应的 PR 在这里:
通过 ISSUES 描述的已知信息,可以看出他遇到的问题跟我是一样的,而这个问题早在 2018 年就提出了。但问题描述不太专业,没有涉及到环境以及最重要的 FastJson 的版本问题。
而通过 PR 可知,这个问题最终在 2020 才解决,期间仅在 ISSUES 区提出的相同问题就有 #1868 #1968 #2029 #2452
4 个。
解决问题的版本为:1.2.72.
这个信息很关键。我对照了我开发环境的版本,是高于 1.2.72 的,所以没有出现测试环境的问题。
所以,柯南告诉我们,排除了所有可能性,剩下的哪怕再可笑,也是最终问题所在。
那就是,测试环境所用的 FastJson 版本是低于 1.2.72 的。
这种可能性是存在的,因为我们用的是 maven 打代码包,依赖包单独存在。
我最终在测试环境的依赖包目录下发现了两个 Fastjson 包,果然不出所料,有一个 1.2.53 的低版本,它就是罪魁祸首。
所以,最终这个问题有相当大的程度是由于我们团队自身问题引发的。但通过解决这个问题的过程也发现了一些有意思的情况。
首先,FastJson 在某一个版本为什么会引发这个问题。它肯定是某个 PR 改出问题的,rv,testcase 覆盖没有到位。
其次,从试图解决这个问题的 3 个 PR 的时间线,分别在 2018 年,2019 年,2020 年。说明,FastJson 这个项目的 contributor 看起来有百来人,但其中过于依赖其中某 1 个或者某些主力人员。精力有限,某些优先级不那么高的 BUG 只能放任。
同时这个项目的荣誉感并没有那么高(或者叫并没有那么吸引高手),它并不是 Apache 顶级项目,要是其它诸如 Spark、Flink、Spring,哪怕是 Dubbo 呢,很想象这些项目会有一个并不算复杂的 BUG 悬而未决长达 3 年时间。在这些顶级开源项目,大家都是拼了老命的想找些 BUG 来提交 PR。
当然,以上只是我个人的一点猜测。
复盘,遇到 FastJson 的问题,一开始就应该奔着 github 的 issues 区,它大概率已经被前人踩坑了。
$ref 循环引用问题
以上测试接口返回前端什么?
我现在并不知道什么循环引用检测,这时候它是我的知识盲区。此时,我观察到的现象是,young
和children
两个 list 对象中均引用指向了王麻子
这个对象。然后,在第 2 次children
引用的时候它在序列化的时候直接指向了第 1 个young
里相应对象引用。当然遇到这个问题的时候,我在仔细观察排除了非 fastjson 的问题以后,这次我学聪明了,我直接来到了 Github 的 issues 区,搜索$ref
。
果然有很多同道中人,近 150 个问题,从时间上来看还挺新鲜。我点击了 closed,既然关闭了,那肯定解决了吧。
我点进了 closed 区第一个问题,然后作者让升级到 fastjson2。???
如果我没有理解错,FastJson 和 FastJson2 可不是两个版本的区别,是两个项目也!据说 API 也有兼容性问题。直接这样升级过去,谈何容易!
我觉得这也是个槽点,FastJson 好像并没有一个稳定维护的版本,遇到问题总是在升级,升级的过程中也没做好质量控制,又引入了新的问题。
还是在当前项目寻求解决方法吧,哪怕升版本也好啊。终于在另一个问题下面找到了问题所在以及解决方案。
我现在知道这是由于循环引用检测引起的。通过设置SerializerFeature.DisableCircularReferenceDetect
可以避免这个问题。
但是,我的代码其实并没有循环引用啊,只是两个子对象引用了同一个对象而已。这算什么?误伤吗?
更重要的,一些控制权应该在使用者手里?
比如,当前这个循环引用在序列化会出的问题,应该是用户手动去开启,而不是默认给用户开启。在优先级上,全局应该关闭,在有循环引用的地方,让用户选择局部开启。
现在我的前端并没有使用 FastJson,面对"$ref":"$.result.young[1]"
这种文本,它能解析吗?它不能呀。
我测试了一下,好像使用 FastJson 也并不能解析回来:
注 :经提醒,这里应使用完整报文解析,经测试,确实可以。感谢提醒!
更可怕的问题是,刚好在测试环节有两个子对象引用了同一个对象,被我提前发现了。如果测试环境没有这样的情况,在生产环境刚好遇到了呢?那就是生产事故了呀。
本来是一个挺好的设计点,能起到锦上添花的作用,但它却可能暴雷,这是好心办坏事。
同样的,还有SerializerFeature.WriteMapNullValue
。如果一个字段值为null
,fastjson 默认就不返回该字段了。本来前后端约定好,如果为null
就怎样处理的逻辑,可能在生产环境中突然暴雷啊。
就像WriteNullListAsEmpty
就很好,不错的设计点,如果返回的 list 为null
的时候,用户可以选择让它序列化为[]
,但它也不是默认开启的呀,给了用户额外的选择权,对吧。
总结
写到这里的时候,我是真心觉得 FastJson 有比竞品有些特色的地方。这真不是为了所谓的客观公正,非要负面写多点,再搞点正面的。
为了写文章,那肯定要去试验,得把竞品也拿出来测试一下,一测试发现并不是 FastJson 独有的,尴尬!
但我还是那句话,不管你信不信,对于开源项目,特别是这样一个广泛使用的开源项目,肯定有非常值得学习的地方。一个开源项目,如果整天拿着显微镜去观察,那肯定能找出不少毛病。
这里稍微总结一下本文的信息点。并不一定是某个具体 BUG,而是通过这个 BUG,解决这个 BUG 背后所展现出来的 FastJson 的信息或趋势。
review
,testcase
覆盖不是很到位contributor
看起来很多,但严重依赖主力人员。而主力精力有限,某些优先级不那么高的 BUG 只能放任。- 这个项目的荣誉感并没有那么高,或者叫并没有那么吸引高手)。
- 有些功能点应该把控制主动权交给用户,如
DisableCircularReferenceDetect
,WriteMapNullValue
等。默认开启非常容易导致线上暴雷。- 作者已经全面转向 fastjosn2,而且哪怕在这之前,对于 fastjson 没有一个稳定维护的版本,不断升级,不断引入新问题。
祝愿 fastjson2 越来越好,不要步 struts2 的后尘。
近期热文推荐:
1.1,000+ 道 Java面试题及答案整理(2022最新版)
4.别再写满屏的爆爆爆炸类了,试试装饰器模式,这才是优雅的方式!!
觉得不错,别忘了随手点赞+转发哦!
iOS 应用程序在 Apple 审批过程中崩溃,但不适合我
【中文标题】iOS 应用程序在 Apple 审批过程中崩溃,但不适合我【英文标题】:iOS App crashes on Apple approval process but not for me 【发布时间】:2013-10-08 08:57:54 【问题描述】:过去两周我一直在尝试更新一个 iOS 客户端应用程序,不幸的是它被拒绝了两次,因为 Apple 说它在 iOS7 上崩溃了。 Apple 已向我发送以下崩溃报告。
Incident Identifier: C213974C-73E2-42C4-A2AA-E4C2A454319E
CrashReporter Key: 2c5d5176cc4387265bd86c427bf138d2b0acfe38
Hardware Model: xxx
Process: Twlight Sports [502]
Path: /var/mobile/Applications/2B9ED7B5-787E-48ED-AAEC-3DEF87A86C67/Twlight Sports.app/Twlight Sports
Identifier: com.twilightsports.twilightsports
Version: 1.2 (1.2)
Code Type: ARM (Native)
Parent Process: launchd [1]
Date/Time: 2013-09-27 15:22:18.784 -0700
OS Version: iOS 7.0 (11A465)
Report Version: 104
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000000e7ffdefe
Triggered by Thread: 0
Dyld Error Message:
Library not loaded: /Developer/Library/Frameworks/SenTestingKit.framework/SenTestingKit
Referenced from: /var/mobile/Applications/2B9ED7B5-787E-48ED-AAEC-3DEF87A86C67/Twlight Sports.app/Twlight Sports
Reason: image not found
Dyld Version: 324
Binary Images:
0x2beed000 - 0x2bf0d78a dyld armv7 <b37cba000c7d3f8ea414f060d45ce144> /usr/lib/dyld
我删除了项目中对SenTestingKit
的所有引用,并再次提交了应用更新。
一周后,我收到了来自 Apple 的完全相同的崩溃报告。
然后,我创建了一个 AdHoc
,与我发送给 Apple 的二进制文件非常相似,并将其部署到我的 iPhone 4S 和 iPad 2 上。这两款设备都可以正常工作而不会崩溃。
我已经对拒绝提出上诉,希望 Apple 会再次测试该应用程序,但他们拒绝了上诉,只是说它仍在崩溃并且不再提供任何帮助。目前我很茫然,因为我无法复制崩溃,因此无法修复它。
我的工作区中还运行着 CocoaPods,并安装了 Kiwi TDD pod。这引用了但是 Pods Build 目标在其 Link Binary With Libraries 中没有 SenTestingKit.framework@
【问题讨论】:
仅凭此描述,我无法为您提供任何帮助。您可能需要发布一些 Xcode 构建设置和构建包的屏幕截图 不清楚您希望这里的任何人如何帮助您处理这些有限的信息。 你在iOS7上也测试过吗? similar issue 为什么要将测试框架链接到您的应用程序中?它们仅属于测试目标。搜索“cocoapods target Exclusive”看看如何。 【参考方案1】:您可以在重新提交之前使用otool
检查您的应用二进制文件,以了解它是否链接SenTestingKit
。 otool -L
将列出 Mach-O 二进制文件的链接库。
例如 Xcode 链接:
% otool -L /Applications/Xcode.app/Contents/MacOS/Xcode
/Applications/Xcode.app/Contents/MacOS/Xcode:
/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 20.0.0)
@rpath/DVTFoundation.framework/Versions/A/DVTFoundation (compatibility version 1.0.0, current version 3532.0.0)
@rpath/DVTKit.framework/Versions/A/DVTKit (compatibility version 1.0.0, current version 3546.0.0)
@rpath/IDEFoundation.framework/Versions/A/IDEFoundation (compatibility version 1.0.0, current version 3569.0.0)
@rpath/IDEKit.framework/Versions/A/IDEKit (compatibility version 1.0.0, current version 3591.0.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1052.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1247.0.0)
您可以通过创建 App Store 构建,将 .ipa
复制到某个文件夹中,在您的应用商店二进制文件上运行它。将.ipa
重命名为.zip
。打开.zip
文件,然后在应用程序内的二进制文件上运行otool -L
,可能是这样的:(这是iBooks)
% cd iBooks\ 3.1.3/Payload/iBooks.app
% otool -L iBooks
iBooks:
/usr/lib/liblockdown.dylib (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/StoreKit.framework/StoreKit (compatibility version 1.0.0, current version 1.0.0)
/System/Library/PrivateFrameworks/Celestial.framework/Celestial (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AssetsLibrary.framework/AssetsLibrary (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 992.0.0)
/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 2372.0.0)
/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics (compatibility version 64.0.0, current version 600.0.0)
/System/Library/PrivateFrameworks/iTunesStoreUI.framework/iTunesStoreUI (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/MediaPlayer.framework/MediaPlayer (compatibility version 1.0.0, current version 1.0.0)
/System/Library/PrivateFrameworks/iTunesStore.framework/iTunesStore (compatibility version 1.0.0, current version 1.0.0)
/System/Library/PrivateFrameworks/StoreServices.framework/StoreServices (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/QuartzCore.framework/QuartzCore (compatibility version 1.2.0, current version 1.8.0)
/System/Library/PrivateFrameworks/GraphicsServices.framework/GraphicsServices (compatibility version 1.0.0, current version 14.0.0)
/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport (compatibility version 1.0.0, current version 29.0.0)
/System/Library/PrivateFrameworks/WebKit.framework/WebKit (compatibility version 1.0.0, current version 536.26.0)
/System/Library/Frameworks/CoreData.framework/CoreData (compatibility version 1.0.0, current version 419.0.0)
/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore (compatibility version 1.0.0, current version 536.26.0)
/System/Library/Frameworks/CFNetwork.framework/CFNetwork (compatibility version 1.0.0, current version 609.0.0)
/System/Library/PrivateFrameworks/WebCore.framework/WebCore (compatibility version 1.0.0, current version 536.26.0)
/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
/System/Library/PrivateFrameworks/Bom.framework/Bom (compatibility version 2.0.0, current version 189.0.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
/System/Library/Frameworks/CoreText.framework/CoreText (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libAccessibility.dylib (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices (compatibility version 1.0.0, current version 40.0.0)
/usr/lib/libsqlite3.dylib (compatibility version 9.0.0, current version 9.6.0)
/System/Library/Frameworks/MessageUI.framework/MessageUI (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AVFoundation.framework/AVFoundation (compatibility version 1.0.0, current version 2.0.0)
/System/Library/Frameworks/ImageIO.framework/ImageIO (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration (compatibility version 1.0.0, current version 499.0.0)
/System/Library/Frameworks/Security.framework/Security (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox (compatibility version 1.0.0, current version 359.0.0)
/usr/lib/libicucore.A.dylib (compatibility version 1.0.0, current version 49.1.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 56.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 173.8.0)
/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 793.0.0)
然后在列表中查找 SenTestingKit
以获取您应用的二进制文件。
【讨论】:
感谢您的回复,如果问题再次出现,我会试一试【参考方案2】:您发布的信息非常有限,但我将从以下步骤开始:
-
您对硬件型号进行了 xxx 处理,但崩溃可能是特定于硬件的,并且可能仅发生在您未测试的硬件上。
与操作系统相同,您可能已在 7.0.1 或 7.0.2 上进行过测试,但根据崩溃报告,它发生在 7.0 上,因此请确保您对此进行了测试。
帮自己一个忙,开始使用 TestFlight 进行崩溃报告,您将不必依赖他人向您发送崩溃报告,而是会自动将崩溃报告发送给您并象征性地发送给您。
在硬件上测试应用时,请确保测试发布配置。优化发布构建时可能会出现很多问题,因此测试发布是这里唯一明智的选择。
您在验证期间是否收到任何警告?如果是,也许您应该认真对待它们?
我假设应用程序没有启动,但在启动时崩溃。在这种情况下,我不确定 TestFlight 是否会对您有很大帮助,相反,我认为您的 Debug 和 Release 配置之间可能存在差异,导致稍后使用 SenTestKit。
【讨论】:
感谢您的回复,我已经尝试使用 Testflight 进行 AdHoc 部署,但它仍然没有崩溃,我不确定如何将我的 7.0.2 设备降级回 7.0,如果这是可能我可以试试。我得到的唯一警告是我没有提供 iOS7 推荐的 150x150 图标,我也会在 iPad 3 上尝试【参考方案3】:嗯.....
为了解决这个问题,我基本上不得不从我的工作区中删除 CocoaPods,删除测试目标和测试方案,我上周四重新提交了应用程序,今天刚刚被接受。
这是一次非常绝望的修复尝试,我认为罪魁祸首是 Apple 正在我的项目上运行我没有正确设置的测试方案。移除 Kiwi Cocoapods 后,看起来它修复了请求 SenTestingKit 框架的任何内容
【讨论】:
很高兴听到它被批准了,同时很遗憾你不得不删除这些东西,因为我很确定你提交了应用程序的 DEBUG 版本。如果是这种情况,将存档方案更改为使用“发布”而不是“调试”就足够了。希望这对您将来有所帮助。 我建议将此信息添加到您帖子的末尾作为更新,而不是作为答案。【参考方案4】:我遇到了类似的问题,即应用程序在我的设备上运行良好但被苹果拒绝。 这是说包中的某些文件已损坏。 当我为所有用户设置读、写和执行权限并再次提交应用程序时,它被批准了。 这可能是您的情况的原因之一。请尝试设置权限并重新创建二进制文件并提交。
【讨论】:
感谢您的回复,您可以在 XCode 中设置此权限吗,我不确定在哪里查看 这些是您可以通过 chmod -R 777以上是关于Fastjson 很快,但不适合我....的主要内容,如果未能解决你的问题,请参考以下文章