美文网首页
“com.alibaba.fastjson”遇到的内存泄漏问题

“com.alibaba.fastjson”遇到的内存泄漏问题

作者: Black哞哞儿 | 来源:发表于2019-10-24 10:55 被阅读0次

    代码不规范,运维两行泪,仅此记录一次因为我们开发的使用错误导致的内存泄漏问题

    遇到的问题就是线上的某服务内存严重不足运维只能kill后重启解决,并且有三至四个服务都暴露出这个问题,那么就说明这个不仅仅只是业务逻辑的bug了,肯定是封装的某个组件有比较严重的内存泄漏问题

    经过定位后发现是在IdentityHashMap存在内存泄露问题

    其他大佬也许遇到类似的问题循环调用JSONObject.parseObject()方法,详见issue

    再次定位问题后,和我遇到的问题还是有些不同,不过总结下来发现的问题点是

    问题一 IdentityHashMap.buckets中的缓存了数据,而其hash key无法命中,亦或者每次添加的key都不尽相同导致缓存的buckets无限变大,最终导致高内存,如何导致的?

    业务需求不太需要feign的出参类型,重写了feign中Decoder的decode()方法,基于ParameterizedType实现泛型类类型参数化

    @Override

    public Object decode(Response response, Type type) {

        ResponseEntity responseEntity;

        ParameterizedTypeImpl parameterizedType = ParameterizedTypeImpl.make(ResponseEntity.class, new Type[]{type}, null);

        if (response.body() == null) return null;

        XXXXXXX............

    }

    泛型类类型参数化

    最后由于new Type[]{type} 每次实例的类型所在的内存不尽相同。com.alibaba.fastjson.util包下的IdentityHashMap类中的hash每次都无法命中之前实例化的对象导致IdentityHashMap.buckets无限变大,最后耗尽所有内存

    IdentityHashMap

    每次的hash值无法命中已有类型,导致buckets无限增加

    问题二 IdentityHashMap.buckets无法命中之因?

    。。。未完待续

    解决方案

    解铃还须系铃人,因为之前编码工作的失误导致的,无法修改第三方组件来满足自己业务需求,既然直接使用 new Type[]{type}会导致缓存无法命中的bug,那么解决方案也比较常规,就是自己把类型先缓存起来

    private final static Map<Type, ParameterizedTypeImpl> TYPE_PARAMETERIZED_CACHE = new HashMap<>();

    private final static Object LOCK = new Object();

    @Override

    public Object decode(Response response, Type type) {

        if (response.body() == null) return null;

        ResponseEntity responseEntity;

        ParameterizedTypeImpl parameterizedType = this.getParameterizedType(type);

        XXXXXXXXXXXX........................

    }

    private ParameterizedTypeImpl getParameterizedType(Type type) {

        ParameterizedTypeImpl parameterizedType= TYPE_PARAMETERIZED_CACHE.get(type);

        if (parameterizedType== null) {

            synchronized (LOCK) {

                parameterizedType= TYPE_PARAMETERIZED_CACHE.get(type); //double check here

                if (parameterizedType== null) {

                    parameterizedType= ParameterizedTypeImpl.make(ResponseEntity.class, new Type[]{type}, null);

                    TYPE_PARAMETERIZED_CACHE.put(type, parameterizedType);

                }

    }

    }

        return parameterizedType;

    }

    相关文章

      网友评论

          本文标题:“com.alibaba.fastjson”遇到的内存泄漏问题

          本文链接:https://www.haomeiwen.com/subject/dbhqdctx.html