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

2019-10-24  本文已影响0人  Black哞哞儿

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

遇到的问题就是线上的某服务内存严重不足运维只能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;

}

上一篇 下一篇

猜你喜欢

热点阅读