在上一次上线完成后,线上的系统在运行几天后就会收到FullGC频繁的告警,而且每台服务都会告警,万能的重启可以解决问题,但不是根本办法,肯定是上一期的代码出现了内存泄漏,在预发环境上,由于操作次数较少,这个问题很难暴露。于是dump 线上的内存,用JProfiler对hprof 文件进行了分析
使用jprofiler打开 dump文件后,在大对象分析中,发现有个http 请求的封装类有居然有130141个实例,着实把我吓了一跳。
这个实例在代码中的确是prototype的,但是在引用他的地方,使用spring的注入方式,不会存在依赖无法释放的问题。在AlphaDataRemoteData 类中目前只存在两个注入的变量
查看Jprofiler实例的引用关系:
可以看到一个FieldValueProcessor 引用了AlphaDataRemoteData这个类,同时也引用了 多例类中注入的@Value;spring的变量注入在populateBean中就会完成,不会生成单独的类,处理注入的value,在看FieldValueProcessor类的包名,猜想应该是引用上次上线引入的中间件导致的问题,引入的中间件的功能是可以在线修改配置变量,不用重启服务就可以生效。该中间件支持spring原生的@Value注入。查看FieldValueProcessor的源码:
确实引用类bean,而最终的GCRoot中是单例的,他内部存储着一个ConcurrentHashMap来缓存这些需要监听的key和key所说的bean,这是一条强依赖的引用链,无法释放;这个类主要负责用户手动点击后,请求其他系统的,5天10万的数量级在数量上也是匹配的,也说明了为什么ConfigruatorManager为什么占用18M内存的原因
目前无法移除这个中间件,窜在两种改法,
原文:https://www.cnblogs.com/arax/p/14857596.html