fastjson charsLocal内存强引用,线程池模式下会导致内存浪费

h5qlskok  于 2022-10-27  发布在  其他
关注(0)|答案(5)|浏览(214)

fastjson/src/main/java/com/alibaba/fastjson/JSON.java

Line 1284 in 14a95cc

| | privatestaticchar[] allocateChars(intlength) { |

private final static ThreadLocal<char[]> charsLocal = new ThreadLocal<char[]>();
    private static char[] allocateChars(int length) {
        char[] chars = charsLocal.get();

        if (chars == null) {
            if (length <= 1024 * 64) {
                chars = new char[1024 * 64];
                charsLocal.set(chars);
            } else {
                chars = new char[length];
            }
        } else if (chars.length < length) {
            chars = new char[length];
        }

        return chars;
    }

直接使用65536个字符是不是太浪费了?大部分场景下都是小对象,但是65536直接内存常驻,利用率非常低,内存水位直接被ThreadLocal拉高,无法GC掉。大对象用不到,小对象还浪费……

nle07wnf

nle07wnf1#

啊这~ 这是大问题啊,简单搜了下, allocateCharsJSON.parse 中被用到,并且完全没有释放的地方。只要100个常驻线程有用过这东西,直接就是6G内存消耗?@wenshao

pinkon5k

pinkon5k2#

啊这~ 这是大问题啊,简单搜了下, allocateCharsJSON.parse 中被用到,并且完全没有释放的地方。只要100个常驻线程有用过这东西,直接就是6G内存消耗?@wenshao

6M,要是6G早就全员原地炸了😂。

mqkwyuun

mqkwyuun3#

最近几天,线上服务器元空间一直在增长, 于是把预发环境机器的内存dump出来看一下, 无意间发现很多Dubbo线程和MQ线程把持了很多内存空间, 上百KB, 不应该呀, 看了业务代码, 看了架构组提供的Jar包是否存在默认拦截器之类的, 但是都没有找到导致问题的根源. 下班后花了2天还是没查到问题, 第3天, 还是回到dump文件, 继续分析它

找了一个MQ线程,看一下它内部属性

继续查看内部的ThreadLocalMap

在它的112槽存储了一个128.05KB字节数组, 里面的信息就是业务打印的日志内容.

继续查看哪些类使用了这个java.lang.ThreadLocal @ 0x701392b28

发现了class com.alibaba.fastjson.JSON @ 0x700f14d78这个对象的charsLocal使用了上面的ThreadLocal

查看源码后, 大吃一惊, 这个ThreadLocal只负责set, 造成很多线程都把持很多无用的信息, 浪费了很多内存空间.

du7egjpx

du7egjpx4#

看上面的回复说, 这个问题已经修复了 . 而经过测试最新的1.2.79版本 以及查看master代码和1.2.79版本代码, fastjson并没有主动帮助使用者清除ThreadLocal. 官方是希望使用者自己去手动清除ThreadLocal? @wenshao

附录
个人理解, 在内存空间和执行效率两者的选择上, fastjson依然选择效率优先, 宁愿牺牲一些内存空间, 也不会放弃效率, 因此也不会调整原有代码逻辑, 是吗?

iecba09b

iecba09b5#

看上面的回复说, 这个问题已经修复了 . 而经过测试最新的1.2.79版本 以及查看master代码和1.2.79版本代码, fastjson并没有主动 帮助 使用者清除ThreadLocal. 官方是希望使用者自己去手动清除ThreadLocal? @wenshao

附录 个人理解, 在内存空间和执行效率两者的选择上, fastjson依然选择效率优先, 宁愿牺牲一些内存空间, 也不会放弃效率, 因此也不会调整原有代码逻辑, 是吗?

Maybe the author has not considered this issue~

相关问题