- 监控的MEM一直居高不下:
- 使用jstat命令查看gc的情况,发现YGC已经停止,一直在FGC,怀疑内存已经泄漏,堆内存中有大量无法回收的对象。
- 然后查看gc日志,发现年轻代和老年代使用率达到99%,且Full GC后内存没有被回收。确定肯定是有对象无法被回收。
- 把堆的dump文件下载下来,用eclipse的mat插件分析error.hprof文件:
发现有个对象占用内存特别大:BouncyCastleProvider();
根据对象定位到项目代码,发现解密方法里用到了该对象:
/**
* 需要解密的数据
* 这是加解密的功能,每次运行加解密都会new一个BouncyCastleProvider对象,放倒Cipher.getInstance()方法中。
* verificationResults.put(var0, PROVIDER_VERIFIED);
* 导致内存被占用儿得不到了回收
* @param data
* @return
* @throws Exception
*/
public static String decrypt(String data) throws Exception {
Cipher cipher = Cipher.getInstance("DES", new BouncyCastleProvider());
return "a";
}
依赖树已经提示了,往里面跟源码,发现verificationResults对象一直在put BouncyCastleProvider()对象,而没有remove,导致BouncyCastleProvider()对象越来越多,最后内存溢出。
final class JceSecurity {
private static final Map<Provider, Object> verificationResults = new IdentityHashMap();
//省略。。。。
static synchronized Exception getVerificationResult(Provider var0) {
Object var1 = verificationResults.get(var0);
if (var1 == PROVIDER_VERIFIED) {
return null;
} else if (var1 != null) {
return (Exception)var1;
} else if (verifyingProviders.get(var0) != null) {
return new NoSuchProviderException("Recursion during verification");
} else {
Exception var3;
try {
verifyingProviders.put(var0, Boolean.FALSE);
URL var2 = getCodeBase(var0.getClass());
verifyProviderJar(var2);
verificationResults.put(var0, PROVIDER_VERIFIED);
var3 = null;
return var3;
} catch (Exception var7) {
verificationResults.put(var0, var7);
var3 = var7;
} finally {
verifyingProviders.remove(var0);
}
return var3;
}
}
}