BouncyCastleProvider导致的内存泄露

young 526 2021-11-05

日志中报错java.lang.OutOfMemoryError: GC overhead limit exceeded

使用memoryanalyzer分析内存发现有占用2.1G内存,进一步查看发现内存都被javax.crypto.JceSecurity类占用

BouncyCastleProviderOOM.png

其中类型为java.util.IdentityHashMap的属性verificationResults占用最多,其中的类型都为org.bouncycastle.jce.provider.BouncyCastleProvider

JceSecuritygetVerificationResult.png
getVerificationResult方法可以看到,只要传入新的Provider,就会缓存到verificationResults

调用链

// ...
Cipher cipher = Cipher.getInstance("RSA",new BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, pubKey); 
// ...

CiphergetInstance.png

此时就会调用JceSecurity.getVerificationResult方法,由于每次都是新创建的BouncyCastleProvider,所以每次调用该方法时,都会进行缓存,导致内存占用无法回收,最终导致OOM

解决方案:
创建BouncyCastleProvider的单例,重复使用,使其只进行一次缓存