来源:https://urlify.cn/NfmaYb

Json-lib 介绍

Json-lib 是以前 Java 常用的一个 Json 库,最后的版本是 2.4,分别提供了 JDK 1.3 和 1.5 的支持,最后更新时间是 2010年12月14日。虽然已经很多年不维护了,但在搜索引擎上搜索 "Java Json" 等相关的关键词发现好像一直还有人在介绍和使用这个库。项目官网是 http://json-lib.sourceforge.net/。

一句话结论

Json-lib 在通过字符串解析每一个 Json 对象时,会对当前解析位置到字符串末尾进行 substring 操作,由于 JDK7 及以上的 substring 会完整拷贝截取后的内容,所以当遇到较大的 Json 数据并且含有较多对象时,会进行大量的字符数组复制操作,导致了大量的 CPU 和内存消耗,甚至严重的 Full GC 问题。

问题分析

某天发现线上生产服务器有不少 Full GC 问题,排查发现产生 Full GC 时某个老接口量会上涨,但这个接口除了解析 Json 外就是将解析后的数据存储到了缓存中,遂怀疑跟接口请求参数大小有关,打日志发现确实有比一般请求大得多的 Json 数据,但也只有 1MB 左右。为了简化这个问题,编写如下的性能测试代码。

package net.mayswind;import net.sf.json.JSONObject;
import org.apache.commons.io.FileUtils;import java.io.File;publicclass JsonLibBenchmark {public static void main(String[] args) throws Exception {String data = FileUtils.readFileToString(new File("Z:\\data.json"));benchmark(data, 5);}private static void benchmark(String data, int count) {long startTime = System.currentTimeMillis();for (int i = 0; i < count; i++) {JSONObject root = JSONObject.fromObject(data);}long elapsedTime = System.currentTimeMillis() - startTime;System.out.println(String.format("count=%d, elapsed time=%d ms, avg cost=%f ms", count, elapsedTime, (double) elapsedTime / count));}
}

上述代码执行后平均每次解析需要 7秒左右才能完成,如下图所示。

测试用的 Json 文件,“...” 处省略了 34,018 个相同内容,整个 Json 数据中包含了 3万多个 Json 对象,实际测试的数据如下图所示。

{"data":[{"foo": 0123456789,"bar": 1234567890},{"foo": 0123456789,"bar": 1234567890},...]
}

使用 Java Mission Control 记录执行的情况,如下图所示,可以看到分配了大量 char[] 数组。

翻看相关源码,其中 JSONObject._fromJSONTokener 方法主要内容如下所示。可以看到其在代码一开始就匹配是否为 "null" 开头。

private static JSONObject _fromJSONTokener(JSONTokener tokener, JsonConfig jsonConfig) {try {if (tokener.matches("null.*")) {fireObjectStartEvent(jsonConfig);fireObjectEndEvent(jsonConfig);returnnew JSONObject(true);} elseif (tokener.nextClean() != '{') {throw tokener.syntaxError("A JSONObject text must begin with '{'");} else {fireObjectStartEvent(jsonConfig);Collection exclusions = jsonConfig.getMergedExcludes();PropertyFilter jsonPropertyFilter = jsonConfig.getJsonPropertyFilter();JSONObject jsonObject = new JSONObject();
...

而 matches 方法更是直接用 substring 截取当前位置到末尾的字符串,然后进行正则匹配。

public boolean matches(String pattern) {String str = this.mySource.substring(this.myIndex);return RegexpUtils.getMatcher(pattern).matches(str);
}

字符串 substring 会传入字符数组、起始位置和截取长度创建一个新的 String 对象。

public String substring(int beginIndex) {if (beginIndex < 0) {thrownew StringIndexOutOfBoundsException(beginIndex);}int subLen = value.length - beginIndex;if (subLen < 0) {thrownew StringIndexOutOfBoundsException(subLen);}return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}

在 JDK7 及以上,调用该构造方法时在最后一行会复制一遍截取后的数据,这也是导致整个问题的关键所在了。

public String(char value[], int offset, int count) {if (offset < 0) {thrownew StringIndexOutOfBoundsException(offset);}if (count <= 0) {if (count < 0) {thrownew StringIndexOutOfBoundsException(count);}if (offset <= value.length) {this.value = "".value;return;}}// Note: offset or count might be near -1>>>1.if (offset > value.length - count) {thrownew StringIndexOutOfBoundsException(offset + count);}this.value = Arrays.copyOfRange(value, offset, offset+count);
}

你们公司还有用这个嘛,留言曝光一下。

猜你喜欢

1、GitHub 标星 3.2w!史上最全技术人员面试手册!FackBoo发起和总结

2、如何才能成为优秀的架构师?

3、从零开始搭建创业公司后台技术栈

4、程序员一般可以从什么平台接私活?

5、37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...

6、滴滴业务中台构建实践,首次曝光

7、不认命,从10年流水线工人,到谷歌上班的程序媛,一位湖南妹子的励志故事

8、15张图看懂瞎忙和高效的区别!

还在用Json-lib?面对疾风吧!相关推荐

  1. 使用JsonConfig控制JSON lib序列化

    原文  http://www.yshjava.cn/post/546.html 将对象转换成字符串,是非常常用的功能,尤其在WEB应用中,使用 JSON lib 能够便捷地完成这项工作.JSON li ...

  2. 金蝶随手记团队分享:还在用JSON? Protobuf让数据传输更省更快(原理篇)

    为什么80%的码农都做不了架构师?>>>    本文作者:丁同舟,转载自"随手记技术团队"微信公众号. 1.前言 跟移动端IM中追求数据传输效率.网络流量消耗等需 ...

  3. 金蝶随手记团队分享:还在用JSON? Protobuf让数据传输更省更快(实战篇)

    本文作者:丁同舟,来自金蝶随手记技术团队. 1.前言 本文接上篇<金蝶随手记团队分享:还在用JSON? Protobuf让数据传输更省更快(原理篇)>,以iOS端的Objective-C代 ...

  4. java json lib 日期

    2019独角兽企业重金招聘Python工程师标准>>> java json lib 日期 博客分类: java JSONObject jsonPerson = JSONObject. ...

  5. Atitit.json类库的设计与实现 ati json lib

    Atitit.json类库的设计与实现 ati json lib 1. 目前jsonlib库可能有问题,可能版本冲突,抛出ex1 2. 解决之道:1 2.1. 自定义json解析库,使用多个复合的js ...

  6. 实现深拷贝还在用JSON.parse(JSON.stringfy(obj))?带你用JS实现一个完整版深拷贝函数

    实现深拷贝还在用JSON.parse(JSON.stringify(obj))?带你用JS实现一个完整版深拷贝函数 目录 实现深拷贝还在用JSON.parse(JSON.stringify(obj)) ...

  7. 学渣!面对疾风吧!哈撒给

    集训本来是24号才开始的,但是我在之前回了趟家感觉在家里特别无聊还不如在学校里,所以我就提前来学校了,听说acm可以提前参加,于是我就提前参加了,现在参加acm的只有14级的学长,和个别15级的成绩比 ...

  8. 面对疾风吧,如何搭建高协同的精准告警体系?

    简介: 想要实现AiOps,智能告警少不了.Arms 告警运维中心让面向告警的组织协同更加便捷高效! 作者|九辩 世上没有一个系统是百分之百尽善尽美的.如果想要保证可用性,那么技术团队就得对服务的各种 ...

  9. JSONObject没有fromObject方法(Json lib 库的使用)

    刚开始还不知道为啥,最后到 jsonlib 网站上查看了原因,这个是连接地址 Json-lib comes in two flavors, depending on the jdk compatibi ...

  10. json lib java_Json-lib 进行java与json字符串转换之二

    二.list和json字符串的互转 list-->>json字符串 public static voidlistToJSON(){ Student stu=newStudent(); st ...

最新文章

  1. java青蛙青蛙跳井_公务员行测技巧:青蛙跳井问题
  2. ZOJ - 3872 Beauty of Array
  3. JVM调优:jdk1.8新生代和老年代的比值是1:2
  4. 做好数据挖掘模型的9条经验总结
  5. 将Java Flight Recorder与OpenJDK 11结合使用
  6. Educational Codeforces Round 73 (Rated for Div. 2)
  7. python特征工程插件_python特征工程
  8. vue:无法将“vue”识别为脚本_Vue3将带来巨大的性能提升
  9. 将20180608141920转成date格式
  10. 9月1日学习内容整理:装饰器带参数,装饰器嵌套
  11. libuv 与 libev 的对比
  12. 汉字编码原则及0XA1与0X80代表的含义。(汉字编码原则为转发)
  13. 方法的重载和重写的区别
  14. PHPStorm+Xdebug配置(phpStudy)
  15. 单片机调试 — Event Recorder 的使用
  16. CLIP改进工作串讲(上)
  17. 使用机器学习数据集构建销售预测Web应用程序
  18. DM达梦数据库dminit使用手册
  19. linux c语言编译成exe,C/C++程序从编译到最终生成可执行文件的过程分析
  20. 粒子群算法求解四维病态方程

热门文章

  1. vue路由vue-router的使用
  2. 【专家专栏】浅谈百度搜索排序
  3. 成为JavaGC专家Part I — 深入浅出Java垃圾回收机制
  4. 一点SICP(Structure and Interpretation of Computer Programs) 资料 (转载加整理)
  5. 快速计算子网掩码和主机块
  6. UNIX环境高级编程之第4章:文件和目录
  7. poj 3660 Cow Contest floyd 传递闭包!!基础
  8. iOS开发之UITextField(输入框)限制只能输入整数和小数
  9. EditRocket for Mac(源代码编辑器)v4.5.10
  10. 如何将Mac中的备忘录内容导出为 PDF文档?