记录一下内存泄漏排查的过程
最近,有个新项目总是无缘无故就down了。排查发现网络,线程都没有异常。最后用jmap拉出dump文件,终于找出原因。
排查过程
- 使用jmap -dump format=b,file=xxx.hprof 1234(pid)拉取dump文件
- 使用mat打开dump文件。观察内存占用,如下图

其中JceSecurity类中的verificationResults属性占据了90%的内存。
verificationResults是一个Map,里面存储了很多BouncyCastleProvider对象。
从一行代码入手
Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
进入源码查询Cipher类的getInstance方法

var1就是传入的BouncyCastleProvider对象。再进入JceSecurity类的getVerificationResult方法

可以发现这个方法会把传入的BouncyCastleProvider对象放入verificationResults中缓存起来,verificationResults是一个Map。
所以每调用一次方法就会将一个BouncyCastleProvider对象放入verificationResults中,而且verificationResults是静态的属性,不会被释放,所以久而久之就会导致内存不够用了。
解决方法
- 解决办法其实很简单,就是将BouncyCastleProvider对象改成单例。