返回

应用fgc排查及解决思路

后端

您好,我是魔性的茶叶,今天分享一个项目jvm多次fgc的整个排查流程。上班后不久运维突然通知我们组,有一个应用在短时间内多次fgc,即将处于挂掉的状态。

首先,我们需要了解一下fgc是什么。fgc是Full GC的缩写,是一种垃圾回收机制,当堆内存空间不足时,JVM会触发fgc,释放所有可回收的对象,以释放内存空间。fgc会暂停所有的应用程序线程,直到完成垃圾回收,因此会对应用程序的性能造成严重影响。

接下来,我们需要找出是什么导致了fgc。可以通过查看JVM的日志文件来了解到更多的信息。在日志文件中,我们可以看到如下信息:

[GC [YG occupancy: 298536K (74.6%) -> 61632K (15.4%), 0 spaces remembered]
[ParNew Desired survivor size 8192K -> 10240K]
[GC [YG occupancy: 62212K (15.6%) -> 0K (0%), 0 spaces remembered]
[ParNew Desired survivor size 10240K -> 12288K]

从日志文件中,我们可以看到,JVM在很短的时间内多次触发了fgc。这表明JVM的堆内存空间不足,导致了fgc的发生。

接下来,我们需要找出是什么导致了堆内存空间不足。可以通过使用jmap工具来获取堆内存的详细信息。jmap工具是一个命令行工具,可以用来获取JVM的堆内存信息。我们可以使用如下命令来获取堆内存的详细信息:

jmap -heap PID

其中,PID是JVM的进程ID。

执行以上命令后,我们可以看到如下信息:

java.lang.Object : 139923
[Ljava.lang.String; : 51422
java.util.HashMap : 34616

从以上信息中,我们可以看到,对象java.lang.Object、数组[Ljava.lang.String;和对象java.util.HashMap占据了堆内存的大部分空间。这表明,这些对象可能导致了堆内存空间不足。

接下来,我们需要找出是什么原因导致了这些对象占据了堆内存的大部分空间。我们可以使用jstack工具来获取JVM的线程堆栈信息。jstack工具是一个命令行工具,可以用来获取JVM的线程堆栈信息。我们可以使用如下命令来获取JVM的线程堆栈信息:

jstack PID

其中,PID是JVM的进程ID。

执行以上命令后,我们可以看到如下信息:

"pool-1-thread-1" #1 prio=5 os_prio=0 tid=0x00007f1d53018000 nid=0x363c runnable [0x00007f1d58155000]
   java.lang.Thread.State: RUNNABLE
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$Node.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1607)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.tryAcquireSharedNanos(AbstractQueuedSynchronizer.java:1309)
	at java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.tryAcquireShared(ReentrantReadWriteLock.java:735)
	at java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.lockShared(ReentrantReadWriteLock.java:709)
	at java.util.HashMap.get(HashMap.java:464)
	at com.xxxx.xxxx.service.impl.UserService.queryUserById(UserService.java:123)

从以上信息中,我们可以看到,线程"pool-1-thread-1"正在执行UserService.queryUserById方法。该方法正在获取HashMap中的数据。这表明,HashMap中的数据可能导致了堆内存空间不足。

接下来,我们需要找出是什么原因导致了HashMap中的数据过多。我们可以使用jvisualvm工具来获取JVM的内存信息。jvisualvm工具是一个图形化工具,可以用来获取JVM的内存信息。我们可以使用如下步骤来获取JVM的内存信息:

  1. 启动jvisualvm工具。
  2. 选择要分析的JVM进程。
  3. 点击"内存"选项卡。

在"内存"选项卡中,我们可以看到如下信息:

堆使用情况:98%
Eden空间使用情况:99%
Survivor空间使用情况:90%

从以上信息中,我们可以看到,堆内存的使用率非常高。这表明,堆内存空间不足,导致了fgc的发生。

接下来,我们需要解决堆内存空间不足的问题。我们可以通过以下几种方法来解决堆内存空间不足的问题:

  1. 增加堆内存的大小。
  2. 减少堆内存中的对象数量。
  3. 使用更少的对象。

在我们的案例中,我们选择了增加堆内存的大小来解决堆内存空间不足的问题。我们通过修改JVM启动参数来增加堆内存的大小。

-Xms256m
-Xmx512m

修改JVM启动参数后,我们重新启动了JVM。fgc不再发生。

以上就是一次应用多次fgc原因的排查及解决过程。