我在拥有8GB内存和4个CPU的机器上运行我的java应用程序。 但是在通过压力测试运行应用程序较长时间之后,观察到垃圾收集器问题,因为内存已经完全充满,并且似乎gc循环需要更长的时间才能完成,但我无法找出可能的原因及其解决方案。 我们的完成请求的avg延迟没有太大差异。但它无法同时为多个线程提供服务。
我已经使用以下参数启动了我的应用程序
-Xms4096M -Xmx4096M
-XX:MaxPermSize=512M
-XX:PermSize=512m
-XX:+UseConcMarkSweepGC
-XX:+HeapDumpOnOutOfMemoryError
-XX:+PrintGCTimeStamps
-XX:+PrintGCDetails
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCApplicationConcurrentTime
-XX:+PrintHeapAtGC
-Xloggc:/root/tomcat_logs/gc_logs.log
输出top命令
top - 11:24:03 up 44 days, 23:45, 1 user, load average: 0.39, 0.47, 0.65
Tasks: 158 total, 1 running, 157 sleeping, 0 stopped, 0 zombie
Cpu(s): 18.8%us, 2.1%sy, 0.0%ni, 64.2%id, 12.9%wa, 0.2%hi, 1.8%si, 0.0%st
Mem: 7672012k total, 7270396k used, 401616k free, 238468k buffers
Swap: 5238776k total, 34584k used, 5204192k free, 2390820k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
15811 root 20 0 7919m 4.1g 9m S 101.1 55.9 4134:37 java
填写内存后的GC日志示例
{Heap before GC invocations=193901 (full 4):
par new generation total 306688K, used 274312K [0x00000006c0000000, 0x00000006d4cc0000, 0x00000006d4cc0000)
eden space 272640K, 100% used [0x00000006c0000000, 0x00000006d0a40000, 0x00000006d0a40000)
from space 34048K, 4% used [0x00000006d2b80000, 0x00000006d2d222c8, 0x00000006d4cc0000)
to space 34048K, 0% used [0x00000006d0a40000, 0x00000006d0a40000, 0x00000006d2b80000)
concurrent mark-sweep generation total 3853568K, used 687930K [0x00000006d4cc0000, 0x00000007c0000000, 0x00000007c0000000)
Metaspace used 58528K, capacity 59902K, committed 61732K, reserved 1103872K
class space used 6866K, capacity 7109K, committed 7464K, reserved 1048576K
89974.407: [GC (Allocation Failure) 89974.407: [ParNew: 274312K->1655K(306688K), 0.0101861 secs] 962243K->689622K(4160256K), 0.0104010 secs] [Times: user=0.04 sys=0.00, real=0.01 secs]
Heap after GC invocations=193902 (full 4):
par new generation total 306688K, used 1655K [0x00000006c0000000, 0x00000006d4cc0000, 0x00000006d4cc0000)
eden space 272640K, 0% used [0x00000006c0000000, 0x00000006c0000000, 0x00000006d0a40000)
from space 34048K, 4% used [0x00000006d0a40000, 0x00000006d0bdded0, 0x00000006d2b80000)
to space 34048K, 0% used [0x00000006d2b80000, 0x00000006d2b80000, 0x00000006d4cc0000)
concurrent mark-sweep generation total 3853568K, used 687966K [0x00000006d4cc0000, 0x00000007c0000000, 0x00000007c0000000)
Metaspace used 58528K, capacity 59902K, committed 61732K, reserved 1103872K
class space used 6866K, capacity 7109K, committed 7464K, reserved 1048576K
}
89974.418: Total time for which application threads were stopped: 0.0127352 seconds
89974.988: Application time: 0.5703336 seconds
我想得出结论为什么内存充满了我可以做些什么来克服它,以便我可以运行我的应用程序更长时间更高的负载。请帮我这样做。
答案 0 :(得分:0)
基本上你面临着可能的内存泄漏。使用YourKIt(或您选择的探查器),运行您的应用程序,并在适当的时候,定期强制垃圾收集,然后检查哪些对象仍然积累尽管强制gc。这可能是一项耗时的活动,但最终会得到回报。
可能的原因可能是ClassLoader泄漏,弱引用,错误实现的缓存或其他任何原因。
答案 1 :(得分:0)
从您提供的日志摘录中可以看到没有问题。
[时间:用户= 0.04 sys = 0.00,实际= 0.01秒]
收集时间为10毫秒。
并发标记扫描生成总计3853568K,使用687966K [0x00000006d4cc0000,0x00000007c0000000,0x00000007c0000000]
老一代只有680MB / 3.8G满。
虽然这只是一个年轻的gen系列,所以也许你已经发布了日志中不可靠的一部分。也许是因为你认为"失败"意味着"坏"?不是这种情况。它只是年轻人收藏的触发器,这意味着如果不首先收集年轻一代就无法满足分配。
您可能希望通过GCViewer运行整个内容,看看您是否真正遇到了GC问题。