场景代码大概如下: 多线程并发请求接口,接口中的代码首先从guavacache.getIfAbsent()查找对象A,假设本地内存没有,代码又调用fetchFromRedisList获取数据,获取到数据后把对象A放到本地内存中 ps:对象A极大,占用大概有几十M
问题分析:首先这里有并发问题,多个线程会同时调用fetchFromRedisList方法并购造成对象A,而不是想象中的只有一个线程去获取,其他线程等待获取结果的guavacache.get(Loadable)模式,导致内存溢出
这里最重要的是怎么从mat分析的内存发现上面的问题的,从导出的堆内存看,每个线程对象下面都"关联"了一个大的A对象,而这个对象A其实并不是FastThreadLocal对象的成员变量,那这里的"关联"是怎么回事呢,其实打开mat的分析结果可以看到线程是通过[java local]的标志关联到对象A的,也就是说是通过方法入参或者方法局部变量关联的,这样就恍然大悟了。ps: mat内存分析中的[java local]标识指方法的入参或者局部变量, [local]标识指native本地方法的变量
附gc图