目前,发现内存溢出在实际应用中常见的有这么两种情况:
一、代码中存在while等循环,导致内存溢出。
二、在后台代码中,部分接口报出内存溢出,但是部分接口正常。
第一种情况解决方案:
第一种情况可以查看代码中的报错日志,一般可以解决,如果实在没有报错,可以按照下面步骤进行排查:
步骤一:通过tasklist定位tomcat运行PID
C:\Users\Administrator\Desktop>tasklist 映像名称 PID 会话名 会话# 内存使用 ========================= ======== ================ =========== ============ System Idle Process 0 Services 0 4 K System 4 Services 0 140 K tomcat9.exe 10740 Services 0 1,578,712 K
步骤二:通过pid查看端口占用情况(如果存在大量端口占用,那么可能是访问网络请求拥堵造成的内存溢出,可以调查具体情况。)
-- 通过指定查询 C:\Users\Administrator\Desktop>netstat -aon | findstr 10740 -- 不指定查询 C:\Users\Administrator\Desktop>netstat -aon 活动连接 协议 本地地址 外部地址 状态 PID TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 4 TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 10740 TCP 127.0.0.1:51373 127.0.0.1:51374 ESTABLISHED 10740 TCP 127.0.0.1:51374 127.0.0.1:51373 ESTABLISHED 10740 TCP 127.0.0.1:61439 127.0.0.1:6380 ESTABLISHED 10740 TCP 172.16.41.128:60289 47.110.8.204:443 CLOSE_WAIT 10740 TCP 172.16.41.128:60315 172.16.41.128:3306 ESTABLISHED 10740 TCP 172.16.41.128:60320 172.16.41.128:3306 ESTABLISHED 10740 TCP 172.16.41.128:60479 47.103.175.115:443 CLOSE_WAIT 10740 TCP 172.16.41.128:60713 47.103.175.115:443 CLOSE_WAIT 10740
步骤三:如果非网络拥堵造成的问题,可以通过jstack(Java Stack Trace,Java堆栈跟踪工具)查看虚拟机当前时刻的线程快照。如果存在死循环(locked <地址信息> (出问题的代码)),可以排除具体代码
C:\Users\Administrator\Desktop>jstack 10740 2025-06-09 11:00:12 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.112-b15 mixed mode): "pool-17-thread-10" #1409 prio=5 os_prio=0 tid=0x000001cffdedd000 nid=0xb5a0 waiting on condition [0x00000042e71ff000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000079a1a2730> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) "VM Thread" os_prio=2 tid=0x000001cff83d9000 nid=0x84a8 runnable "GC task thread#0 (ParallelGC)" os_prio=0 tid=0x000001cfdebc7000 nid=0xc15c runnable "GC task thread#1 (ParallelGC)" os_prio=0 tid=0x000001cfdebc8800 nid=0x35e0 runnable "GC task thread#2 (ParallelGC)" os_prio=0 tid=0x000001cfdebca000 nid=0xb080 runnable "GC task thread#3 (ParallelGC)" os_prio=0 tid=0x000001cfdebcb800 nid=0x4644 runnable "GC task thread#4 (ParallelGC)" os_prio=0 tid=0x000001cfdebce000 nid=0x2b74 runnable "GC task thread#5 (ParallelGC)" os_prio=0 tid=0x000001cfdebcf000 nid=0x3a90 runnable "GC task thread#6 (ParallelGC)" os_prio=0 tid=0x000001cfdebd3000 nid=0x7c18 runnable "GC task thread#7 (ParallelGC)" os_prio=0 tid=0x000001cfdebd4800 nid=0xb2ac runnable "VM Periodic Task Thread" os_prio=2 tid=0x000001cffa22e800 nid=0xd55c waiting on condition JNI global references: 7181 C:\Users\Administrator\Desktop>
第二种情况解决方案:
代码没问题,但是代码里层的嵌套太深,导致报出:StackOverflow,并且是在dofilter层溢出。
这种情况,可以简化流程、将可以异步的步骤进行异步处理。
发生这种情况的原因:
1、可能是计算机内存真的太小;
2、jvm配置不合理。
关于ParallelGCThreads不合理,可以参考JVM参数之ParallelGCThreads_-xx:parallelgcthreads-CSDN博客