java - 使用不同用户执行jstack导致Full GC

标签 java garbage-collection jvm jstack

我用tomcat用户启动tomcat,并执行jstack与 root 用户。我检查了gc日志,发现发生了Full GC。

我搜索并找到sudo -u tomcat jstack -l <pid>将解决问题。但是为什么root用户的jstack会导致full gc呢?

环境:

[root@bogon ~]# cat /etc/redhat-release 
CentOS release 6.8 (Final)
[root@bogon ~]# java -version
java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)
[root@bogon ~]# service tomcat version
vagrant: Display Tomcat Version
Using CATALINA_BASE:   /apps/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /apps/tomcat/temp
Using JRE_HOME:        /usr/java/jdk1.8.0_65/
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Server version: Apache Tomcat/8.5.11
Server built:   Jan 10 2017 21:02:52 UTC
Server number:  8.5.11.0
OS Name:        Linux
OS Version:     2.6.32-642.15.1.el6.x86_64
Architecture:   amd64
JVM Version:    1.8.0_65-b17
JVM Vendor:     Oracle Corporation



[root@bogon tomcat]# jstack -l 2644
2644: Unable to open socket file: target process not responding or HotSpot VM not loaded
The -F option can be used when the target process is not responding

GC日志

CommandLine flags: -XX:+DisableExplicitGC -XX:GCLogFileSize=2097152 -XX:+HeapDumpOnOutOfMemoryError -XX:InitialHeapSize=1149239296 -XX:InitiatingHeapOccupancyPercent=45 -XX:+ManagementServer -XX:MaxGCPauseMillis=200 -XX:MaxHeapSize=1149239296 -XX:MaxMetaspaceFreeRatio=80 -XX:MetaspaceSize=100663296 -XX:MinMetaspaceFreeRatio=50 -XX:NumberOfGCLogFiles=10 -XX:+PrintClassHistogram -XX:+PrintGC -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintTenuringDistribution -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC -XX:+UseGCLogFileRotation -XX:+UseStringDeduplication

2017-07-05T20:13:10.591+0800: 38.999: [Full GC (Heap Inspection Initiated GC)  47M->13M(1096M), 0.0710197 secs]
   [Eden: 48.0M(54.0M)->0.0B(54.0M) Survivors: 0.0B->0.0B Heap: 47.5M(1096.0M)->13.2M(1096.0M)], [Metaspace: 15845K->15845K(1062912K)]
 [Times: user=0.04 sys=0.02, real=0.07 secs]

 num     #instances         #bytes  class name
----------------------------------------------
   1:         27256        5409512  [C
   2:          2889        3734776  [B
   3:            28         935336  [J
   4:         26366         632784  java.lang.String
   5:          4464         392832  java.lang.reflect.Method
   6:          2964         338128  java.lang.Class
   7:          9495         303840  java.util.HashMap$Node
   8:          1566         203296  [I
   9:          2576         167120  [Ljava.lang.Object;
  10:           971         120680  [Ljava.util.HashMap$Node;
  11:          3610         115520  java.util.concurrent.ConcurrentHashMap$Node
  12:          3335          69056  [Ljava.lang.Class;
  13:           924          67912  [Ljava.lang.String;
  14:          1697          67880  java.lang.ref.Finalizer
  15:          1608          64320  java.util.LinkedHashMap$Entry
  16:          1232          59136  java.util.HashMap
  17:           652          52160  java.lang.reflect.Constructor
  18:          3243          51888  java.lang.Object
  19:          1453          46496  java.util.Hashtable$Entry
  20:          1027          41080  java.util.TreeMap$Entry
  21:           711          39816  java.util.zip.ZipFile$ZipFileInputStream
  22:           708          39648  java.util.zip.ZipFile$ZipFileInflaterInputStream
  23:           308          37176  [Ljava.lang.reflect.Method;
  24:           764          36672  org.apache.tomcat.util.modeler.AttributeInfo
  25:            56          31968  [Ljava.util.concurrent.ConcurrentHashMap$Node;
  26:           442          31824  java.lang.reflect.Field
  27:            30          31200  [[C

最佳答案

在您的情况下,GC是由-XX:+PrintClassHistogram选项引起的。该标志强制堆检查伴随着 Full GC,以响应 SIGQUIT 信号。

正如您可以从 this answer 找到的,jstack 使用SIGQUIT 发起与目标 JVM 的通信。同样的答案解释了为什么jstack可以在tomcat用户下工作,但不能在root用户下工作。

简而言之,SIGQUIT(也称为kill -3)扮演两个角色:启动动态附加和转储JVM 状态。如果动态附加失败,则 JVM 会继续进行堆检查,进而导致 Full GC,因为 -XX:+PrintClassHistogram 选项已打开。

关于java - 使用不同用户执行jstack导致Full GC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44926255/

相关文章:

kotlin - 如何强制立即实例化枚举值?

java - Shenandoah 2.0 消除转发指针

java - 从 datasource.getConnection() 获取 OracleConnection

java - 如何: Hibernate 3. xx条件查询

java - System.nanoTime() 变为负值

java - Tomcat 上的新 Relic JVM 图表

java - 使用弱(或软等)引用作为树中的父引用是否值得?

Java 从端口上的服务器读取返回 -1

java - Java 中的清除 protected 双向链表

java - 为什么 java.lang.Object.getClass() (和反射)比平时慢?