tomcat内存溢出怎么解决_疫情当下远程办公-解决服务内存溢出问题

a75a1a51ebcff7976732e11313e46220.png

目前疫情还在持续,在家休息也20多天了,很久没更新文章了。今天公司的微信预警上收到服务宕机的信息,远程连接发现服务进程还在但出现如下错误信息:

xxxx系统异常,异常信息:org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded

典型的内存溢出问题,分析这种问题我多种思路去解决这里我介绍下我排查这个问题的过程和大家分享下:

1.查看服务jvm内存使用情况

我们通过jmap命令实现,通过jmap命令我们可以很详细的查看内存使用情况汇总、及对内存溢出进行定位与分析。

1.1.定位服务进程

jps -l

1.2.根据进程分析内存使用情况

jmap -heap 31650

我们得到的内存分析结果如下:

Attaching to process ID 12112, please wait...Debugger attached successfully.Server compiler detected.JVM version is 25.162-b12using thread-local object allocation.Parallel GC with 2 thread(s)Heap Configuration:   MinHeapFreeRatio         = 0   MaxHeapFreeRatio         = 100   MaxHeapSize              = 536870912 (512.0MB)   NewSize                  = 178782208 (170.5MB)   MaxNewSize               = 178782208 (170.5MB)   OldSize                  = 358088704 (341.5MB)   NewRatio                 = 2   SurvivorRatio            = 8   MetaspaceSize            = 21807104 (20.796875MB)   CompressedClassSpaceSize = 1073741824 (1024.0MB)   MaxMetaspaceSize         = 17592186044415 MB   G1HeapRegionSize         = 0 (0.0MB)Heap Usage:PS Young GenerationEden Space:   capacity = 170393600 (162.5MB)   used     = 164111320 (156.50875091552734MB)   free     = 6282280 (5.991249084472656MB)   96.31307748647836% usedFrom Space:   capacity = 524288 (0.5MB)   used     = 0 (0.0MB)   free     = 524288 (0.5MB)   0.0% usedTo Space:   capacity = 4718592 (4.5MB)   used     = 0 (0.0MB)   free     = 4718592 (4.5MB)   0.0% usedPS Old Generation   capacity = 358088704 (341.5MB)   used     = 357753512 (341.18033599853516MB)   free     = 335192 (0.31966400146484375MB)   99.90639414305568% used

通过分析我们看到Old Generation老年代的使用率达到99.9%,导致没有足够的内存进行GC操作,这就是导致程序内存溢出的原因。

那具体是哪里导致的呢?这里就要进行下一步的操作。

2.将内存使用情况dump到文件中

我们执行如下命令:

jmap -dump:format=b,file=/home/wxt/dump.dat 31650

我们将内存使用dump到我们指定目录下,dump完成后进行我们最重要的一步,内存分析。

3.通过heaphero分析内存

jvm的内存分析工具要很多像jhat,这里我介绍一款在线分析工具heaphero,网站地址:

https://heaphero.io/heap-index.jsp#header

414e0e6668946c34feee98994f77eee3.png

我们将dump下来的内存文件上传后可以得到如下的分析结果:

我们定位到Large objects部分:

c9a83ee68e0a59ad8affde85839dbebe.png

我们看到 Java Static javax.crypto.JceSecurity.verificationResults
<>这里内存的占用达到了89.3%,显然是很不正常的。我们进入连接后进一步分析发现:javax.crypto.JceSecurity.verificationResults的实例占用了最多的堆内存,主要是一个IdentityHashMap类型的属性verificationResults,放了很多org.bouncycastle.jce.provider.BouncyCastleProvider对象(达到251,062K )。

通过对源代码进行分析我们定位到了如下代码块:

private static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception {if (publicKey == null) {throw new Exception("加密公钥为空, 请设置");}Cipher cipher = null;byte[] output = null;try {cipher = Cipher.getInstance("RSA", new BouncyCastleProvider());cipher.init(Cipher.ENCRYPT_MODE, publicKey);output = cipher.doFinal(plainTextData);return output;} catch (Exception e) {MySlf4j.textError("公钥加密过程异常:{0}", MySlf4j.ExceptionToString(e));throw e;}}

每次new BouncyCastleProvider 都会产生非常多的对象和引用(占用251,062K ),且缓存在JceSecurity的verificationResults没法释放。

找到问题后解决就很简单了,将BouncyCastleProvider实例对象作为Rsa的静态成员变量可以解决问题。

private static Provider bouncyCastleProvider=new BouncyCastle.......cipher = Cipher.getInstance("RSA", bouncyCastleProvider);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值