美文网首页JVM
JVM性能调优指南(一)

JVM性能调优指南(一)

作者: 大厂offer | 来源:发表于2018-10-07 09:53 被阅读182次

    1、JVM的参数类型

    1.1 标准参数:在各jdk版本中较稳定

    -help
    -server -client
    -version -showversion
    -cp -classpath

    1.2 X参数

    1.2.1非标准化参数
    1.2.2 -Xint:完全解释执行

    调整为完全解释执行编译模式:

    MacBook-Pro:dubbo-learn chuanzhou$ java -Xint -version
    java version "1.8.0_161"
    Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
    Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, interpreted mode)
    
    1.2.3 -Xcomp:第一次使用就编译成本地代码

    调整为编译执行编译模式:

    MacBook-Pro:dubbo-learn chuanzhou$ java -Xcomp -version
    java version "1.8.0_161"
    Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
    Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, compiled mode)
    
    1.2.4 -Xmixed:混合模式,JVM自己来决定是否编译成本地代码
    MacBook-Pro:~ chuanzhou$ java -version
    java version "1.8.0_161"
    Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
    Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)
    

    最后一行的mixed mode表明JVM默认使用的编译模式是混合模式

    1.3 XX参数

    使用最多的一种参数类型

    1.3.1 Boolean类型

    格式:-XX:[+/-] <name> 表示启用或者禁用name属性
    比如:
    -XX:+UseConcMarkSweepGC 表示启用CMS垃圾回收器
    -XX:+UseG1GC 表示启用G1垃圾回收器

    1.3.2 非Boolean类型

    格式:-XX:<name> = <value> 表示name属性的值为value
    比如:
    -XX:MaxGCPauseMillis=500 表示GC最大停顿时间是500毫秒
    -XX:GCTimeRatio=19 表示...

    1.3.3 -Xmx -Xms

    虽然1以X开头,但是不是X类型参数,而是XX类型的参数

    • -Xmx等价于-XX:MaxHeapSize 表示最大堆内存大小,可使用jinfo -flag MaxHeapSize 进程id查看,如下:
    [root@izwz93osmk5vi5qwqyscxaz bin]# ps -ef|grep java
    root      9723     1  0 4月24 ?       04:28:59 /usr/program/jdk1.8.0_72/jre/bin/java -Djava.util.logging.config.file=/opt/tomcat/apache-tomcat-8.0.50/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dignore.endorsed.dirs= -classpath /opt/tomcat/apache-tomcat-8.0.50/bin/bootstrap.jar:/opt/tomcat/apache-tomcat-8.0.50/bin/tomcat-juli.jar -Dcatalina.base=/opt/tomcat/apache-tomcat-8.0.50 -Dcatalina.home=/opt/tomcat/apache-tomcat-8.0.50 -Djava.io.tmpdir=/opt/tomcat/apache-tomcat-8.0.50/temp org.apache.catalina.startup.Bootstrap start
    root     20037 19984  0 20:53 pts/2    00:00:00 grep --color=auto java
    [root@izwz93osmk5vi5qwqyscxaz bin]# ./jinfo -flag MaxHeapSize 9723
    -XX:MaxHeapSize=482344960
    [root@izwz93osmk5vi5qwqyscxaz bin]#
    
    • -Xms等价于-XX:InitalHeapSize 表示堆内存初始大小

    • -Xss等价于-XX:InitalStackSize 表示线程栈的初始大小,可以使用jinfo -flag ThreadStackSize 进程id查看,如下:

    [root@izwz93osmk5vi5qwqyscxaz bin]# ps -ef
    [root@izwz93osmk5vi5qwqyscxaz bin]# ps -ef|grep java
    root      9723     1  0 4月24 ?       04:28:59 /usr/program/jdk1.8.0_72/jre/bin/java -Djava.util.logging.config.file=/opt/tomcat/apache-tomcat-8.0.50/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dignore.endorsed.dirs= -classpath /opt/tomcat/apache-tomcat-8.0.50/bin/bootstrap.jar:/opt/tomcat/apache-tomcat-8.0.50/bin/tomcat-juli.jar -Dcatalina.base=/opt/tomcat/apache-tomcat-8.0.50 -Dcatalina.home=/opt/tomcat/apache-tomcat-8.0.50 -Djava.io.tmpdir=/opt/tomcat/apache-tomcat-8.0.50/temp org.apache.catalina.startup.Bootstrap start
    root     20037 19984  0 20:53 pts/2    00:00:00 grep --color=auto java
    [root@izwz93osmk5vi5qwqyscxaz bin]# ./jinfo -flag MaxHeapSize 9723
    -XX:MaxHeapSize=482344960
    [root@izwz93osmk5vi5qwqyscxaz bin]# ./jinfo -flag ThreadStackSize 9723
    -XX:ThreadStackSize=1024
    [root@izwz93osmk5vi5qwqyscxaz bin]#
    

    2、JVM运行时参数查看

    • -XX:+printFlagsInitial 查看JVM运行时初始值
    • -XX:+printFlagsFinal 查看JVM运行时最终值
    • -XX:+UnlockExperimentalVMOptions 解锁实验参数
    • -XX:+UnlockDiagnosticVMOptions 解锁诊断参数
    • -XX:+PrintCommandLineFlags 打印命令行参数

    如查看JVM版本信息:java -XX:+PrintFlagsFinal -version > ~/version.txt

    version.txt中部分参数:
    [Global flags]
        uintx AdaptiveSizeDecrementScaleFactor          = 4                                   {product}
        uintx AdaptiveSizeMajorGCDecayTimeScale         = 10                                  {product}
        uintx AdaptiveSizePausePolicy                   = 0                                   {product}
        uintx AdaptiveSizePolicyCollectionCostMargin    = 50                                  {product}
        uintx AdaptiveSizePolicyInitializingSteps       = 20                                  {product}
        uintx AdaptiveSizePolicyOutputInterval          = 0                                   {product}
        uintx AdaptiveSizePolicyWeight                  = 10                                  {product}
        uintx AdaptiveSizeThroughPutPolicy              = 0                                   {product}
        uintx AdaptiveTimeWeight                        = 25                                  {product}
         bool AdjustConcurrency                         = false                               {product}
         bool AggressiveOpts                            = false                               {product}
         bool C1ProfileVirtualCalls                     = true                                {C1 product}
         bool C1UpdateMethodData                        = true                                {C1 product}
         intx CICompilerCount                          := 2                                   {product}
         bool CICompilerCountPerCPU                     = true                                {product}
         bool CITime                                    = false                               {product}
         bool CMSAbortSemantics                         = false                               {product}
        uintx CMSAbortablePrecleanMinWorkPerIteration   = 100                                 {product}
         intx CMSAbortablePrecleanWaitMillis            = 100                                 {manageable}
        uintx CMSBitMapYieldQuantum                     = 10485760
    

    注:=表示默认值,=:表示修改后的值

    jps:查看Java进程

    [root@izwz93osmk5vi5qwqyscxaz bin]# ./jps
    20160 Jps
    9723 Bootstrap
    [root@izwz93osmk5vi5qwqyscxaz bin]# ./jps -l
    20170 sun.tools.jps.Jps
    9723 org.apache.catalina.startup.Bootstrap
    [root@izwz93osmk5vi5qwqyscxaz bin]#
    

    关于jps等命令的详解,可参考此文档https://docs.oracle.com/javase/8/docs/technotes/tools/unix/index.html

    jinfo:查看指定Java进程运行时参数

    如查看一个java进程id为9723的tomcat服务最大堆内存大小

    [root@izwz93osmk5vi5qwqyscxaz bin]# ps -ef|grep java
    root      9723     1  0 4月24 ?       04:29:03 /usr/program/jdk1.8.0_72/jre/bin/java -Djava.util.logging.config.file=/opt/tomcat/apache-tomcat-8.0.50/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dignore.endorsed.dirs= -classpath /opt/tomcat/apache-tomcat-8.0.50/bin/bootstrap.jar:/opt/tomcat/apache-tomcat-8.0.50/bin/tomcat-juli.jar -Dcatalina.base=/opt/tomcat/apache-tomcat-8.0.50 -Dcatalina.home=/opt/tomcat/apache-tomcat-8.0.50 -Djava.io.tmpdir=/opt/tomcat/apache-tomcat-8.0.50/temp org.apache.catalina.startup.Bootstrap start
    root     20187 20123  0 21:34 pts/2    00:00:00 grep --color=auto java
    [root@izwz93osmk5vi5qwqyscxaz bin]# ./jinfo -flag MaxHeapSize 9723
    -XX:MaxHeapSize=482344960
    [root@izwz93osmk5vi5qwqyscxaz bin]#
    

    查看一个进程的所有运行时参数:

    [root@izwz93osmk5vi5qwqyscxaz bin]# ./jinfo -flags 9732
    Attaching to process ID 9732, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.72-b15
    Non-default VM flags: -XX:CICompilerCount=2 
    -XX:InitialHeapSize=31457280 -XX:MaxHeapSize=482344960 
    -XX:MaxNewSize=160759808 -XX:MinHeapDeltaBytes=196608 
    -XX:NewSize=10485760 -XX:OldSize=20971520 
    -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
    Command line:  -Djava.util.logging.config.file=/opt/tomcat/apache-tomcat-8.0.50/conf/logging.properties 
    -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 
    -Djava.protocol.handler.pkgs=org.apache.catalina.webresources 
    -Dignore.endorsed.dirs= -Dcatalina.base=/opt/tomcat/apache-tomcat-8.0.50 
    -Dcatalina.home=/opt/tomcat/apache-tomcat-8.0.50 
    -Djava.io.tmpdir=/opt/tomcat/apache-tomcat-8.0.50/temp
    [root@izwz93osmk5vi5qwqyscxaz bin]#
    

    Non-default VM flags表示手动赋值过的参数,其中有些是tomcat设置的
    Command line:与Non-default VM flags

    查看垃圾回收器信息

    MacBook-Pro:dubbo-learn chuanzhou$ jinfo -flag UseConcMarkSweepGc 29159
    no such flag 'UseConcMarkSweepGc'
    MacBook-Pro:dubbo-learn chuanzhou$ jinfo -flag UseG1Gc 29159
    no such flag 'UseG1Gc'
    MacBook-Pro:dubbo-learn chuanzhou$ jinfo -flag UseParallelGc 29159
    no such flag 'UseParallelGc'
    

    3、jstat查看虚拟机统计信息

    3.1 类装载

    格式:jstat -class 进程id 每隔多少毫秒 一共输出多少次
    如:查看一个进程id为29159的java进程,每隔1s输出,一共输出10次

    MacBook-Pro:dubbo-learn chuanzhou$ jstat -class 29159 1000 10
    Loaded  Bytes  Unloaded  Bytes     Time
      3204  6088.2        0     0.0       2.14
      3204  6088.2        0     0.0       2.14
      3204  6088.2        0     0.0       2.14
      3204  6088.2        0     0.0       2.14
      3204  6088.2        0     0.0       2.14
      3204  6088.2        0     0.0       2.14
      3204  6088.2        0     0.0       2.14
      3204  6088.2        0     0.0       2.14
      3204  6088.2        0     0.0       2.14
      3204  6088.2        0     0.0       2.14
    
    • Loaded:表示类加载的个数
    • Bytes:表示类加载的大小,单位为kb
    • UnLoaded:表示类卸载的个数
    • Bytes:表示类卸载的大小,单位为kb
    • Time:表示类加载和卸载的时间

    3.2 垃圾收集

    要查看一个java进程的垃圾收集器信息,可使用jstat -gc 进程id 每隔多少毫秒 一共输出多少次

    MacBook-Pro:dubbo-learn chuanzhou$ jstat -gc 29159 1000 3
     S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
    5120.0 5120.0 4308.8  0.0   33280.0  17845.6   87552.0      88.0    18944.0 18304.7 2304.0 2144.9      2    0.014   0      0.000    0.014
    5120.0 5120.0 4308.8  0.0   33280.0  17845.6   87552.0      88.0    18944.0 18304.7 2304.0 2144.9      2    0.014   0      0.000    0.014
    5120.0 5120.0 4308.8  0.0   33280.0  17845.6   87552.0      88.0    18944.0 18304.7 2304.0 2144.9      2    0.014   0      0.000    0.014
    

    S0C: Current survivor space 0 capacity (kB).表示survivor 0区的总大小
    S1C: Current survivor space 1 capacity (kB).表示survivor 1区的总大小
    S0U: Survivor space 0 utilization (kB).表示survivor 0区使用了的大小
    S1U: Survivor space 1 utilization (kB).表示survivor 1区使用了的大小
    EC: Current eden space capacity (kB).表示eden区总大小
    EU: Eden space utilization (kB).表示eden区使用了的大小
    OC: Current old space capacity (kB).表示old区总大小
    OU: Old space utilization (kB).表示old区使用了的大小
    MC: Metaspace capacity (kB).表示Metaspace区总大小
    MU: Metacspace utilization (kB).表示Metaspace区使用了的大小
    CCSC: Compressed class space capacity (kB).表示压缩类空间总量
    CCSU: Compressed class space used (kB).表示压缩类空间使用量
    YGC: Number of young generation garbage collection events.表示Young GC的次数
    YGCT: Young generation garbage collection time.表示Young GC的时间
    FGC: Number of full GC events.表示full GC的次数
    FGCT: Full garbage collection time.表示full GC的时间
    GCT: Total garbage collection time.表示总的 GC的时间

    3.3 JIT编译

    3.3.1 -compiler参数
    MacBook-Pro:dubbo-learn chuanzhou$ jstat -compiler 29159 1000 5
    Compiled Failed Invalid   Time   FailedType FailedMethod
        1284      0       0     3.50          0
        1284      0       0     3.50          0
        1284      0       0     3.50          0
        1284      0       0     3.50          0
        1284      0       0     3.50          0
    
    • Compiled:表示编译成功的方法数量
    • Failed:表示编译失败的方法数量
    • Invalid:表示编译无效的方法数量
    • Time:编译所花费的时间
    • FailedType:编译失败类型
    • FailedMethod:编译失败方法
    3.3.2 -printcompilation参数

    4、jmap+MAT实战内存溢出

    模拟内存溢出:

    @RestController
    public class MemoryController {
        
        private List<User>  userList = new ArrayList<User>();
        private List<Class<?>>  classList = new ArrayList<Class<?>>();
        
        /**
         * -Xmx32M -Xms32M
         * */
        @GetMapping("/heap")
        public String heap() {
            int i=0;
            while(true) {
                userList.add(new User(i++, UUID.randomUUID().toString()));
            }
        }
        
        
        /**
         * -XX:MetaspaceSize=32M -XX:MaxMetaspaceSize=32M
         * */
        @GetMapping("/nonheap")
        public String nonheap() {
            while(true) {
                classList.addAll(Metaspace.createClasses());
            }
        }
        
    }
    
    
    package com.imooc.monitor_tuning.chapter2;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.objectweb.asm.ClassWriter;
    import org.objectweb.asm.MethodVisitor;
    import org.objectweb.asm.Opcodes;
    
    /*
     * https://blog.csdn.net/bolg_hero/article/details/78189621
     * 继承ClassLoader是为了方便调用defineClass方法,因为该方法的定义为protected
     * */
    public class Metaspace extends ClassLoader {
        
        public static List<Class<?>> createClasses() {
            // 类持有
            List<Class<?>> classes = new ArrayList<Class<?>>();
            // 循环1000w次生成1000w个不同的类。
            for (int i = 0; i < 10000000; ++i) {
                ClassWriter cw = new ClassWriter(0);
                // 定义一个类名称为Class{i},它的访问域为public,父类为java.lang.Object,不实现任何接口
                cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "Class" + i, null,
                        "java/lang/Object", null);
                // 定义构造函数<init>方法
                MethodVisitor mw = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>",
                        "()V", null, null);
                // 第一个指令为加载this
                mw.visitVarInsn(Opcodes.ALOAD, 0);
                // 第二个指令为调用父类Object的构造函数
                mw.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object",
                        "<init>", "()V");
                // 第三条指令为return
                mw.visitInsn(Opcodes.RETURN);
                mw.visitMaxs(1, 1);
                mw.visitEnd();
                Metaspace test = new Metaspace();
                byte[] code = cw.toByteArray();
                // 定义类
                Class<?> exampleClass = test.defineClass("Class" + i, code, 0, code.length);
                classes.add(exampleClass);
            }
            return classes;
        }
    }
    
    package com.imooc.monitor_tuning.chapter2;
    
    public class User {
        private int id;
        private String name;
        public User(int id, String name) {
            super();
            this.id = id;
            this.name = name;
        }
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
    }
    
    

    设置启动参数:


    启动参数

    启动application,发现出现内存溢出

    4.1 如何导出内存溢出映像文件

    4.2 内存溢出自动导出

    -XX:+HeapDumpOnOutOfMemoryError
    -XX:HeapDumpPath=./

    4.3 使用jmap命令手动导出

    格式:jmap -dump:format=b,file=路径/heap.hprof 进程id
    其他命令:jmap -heap 进程id 查看堆信息

    [root@izwz93osmk5vi5qwqyscxaz bin]# ./jmap -heap 9723
    Attaching to process ID 9723, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.72-b15
    
    using thread-local object allocation.
    Mark Sweep Compact GC
    
    Heap Configuration:
       MinHeapFreeRatio         = 40
       MaxHeapFreeRatio         = 70
       MaxHeapSize              = 482344960 (460.0MB)
       NewSize                  = 10485760 (10.0MB)
       MaxNewSize               = 160759808 (153.3125MB)
       OldSize                  = 20971520 (20.0MB)
       NewRatio                 = 2
       SurvivorRatio            = 8
       MetaspaceSize            = 21807104 (20.796875MB)
       CompressedClassSpaceSize = 1073741824 (1024.0MB)
       MaxMetaspaceSize         = 17592186044415 MB
       G1HeapRegionSize         = 0 (0.0MB)
    
    Heap Usage:
    New Generation (Eden + 1 Survivor Space):
       capacity = 32178176 (30.6875MB)
       used     = 16081160 (15.336189270019531MB)
       free     = 16097016 (15.351310729980469MB)
       49.97536218336303% used
    Eden Space:
       capacity = 28639232 (27.3125MB)
       used     = 16054760 (15.311012268066406MB)
       free     = 12584472 (12.001487731933594MB)
       56.058626153103546% used
    From Space:
       capacity = 3538944 (3.375MB)
       used     = 26400 (0.025177001953125MB)
       free     = 3512544 (3.349822998046875MB)
       0.7459852430555556% used
    To Space:
       capacity = 3538944 (3.375MB)
       used     = 0 (0.0MB)
       free     = 3538944 (3.375MB)
       0.0% used
    tenured generation:
       capacity = 71221248 (67.921875MB)
       used     = 57115304 (54.469398498535156MB)
       free     = 14105944 (13.452476501464844MB)
       80.19419148622613% used
    
    27532 interned Strings occupying 3194040 bytes.
    
    4.4 使用MAT分析映像文件
    MAT分析
    • Class Name:类名
    • Objects:对象数量
    • Shallow Heap:
    • Retained Heap:占用的内存大小

    右键查看com.imooc.monitor_tuning.chapter2.User的强引用


    image.png image.png

    也可以查看对象树:


    对象树

    5、jstack实战死循环与死锁

    格式:jstack 进程id

    2018-09-05 07:59:21
    Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.72-b15 mixed mode):
    
    "Attach Listener" #16 daemon prio=9 os_prio=0 tid=0x00007f3d9c001000 nid=0x521f waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "localhost-startStop-1" #15 daemon prio=5 os_prio=0 tid=0x00007f3dac002800 nid=0x5208 runnable [0x00007f3da15d1000]
       java.lang.Thread.State: RUNNABLE
        at java.io.FileInputStream.readBytes(Native Method)
        at java.io.FileInputStream.read(FileInputStream.java:255)
        at sun.security.provider.SeedGenerator$URLSeedGenerator.getSeedBytes(SeedGenerator.java:539)
        at sun.security.provider.SeedGenerator.generateSeed(SeedGenerator.java:144)
        at sun.security.provider.SecureRandom$SeederHolder.<clinit>(SecureRandom.java:203)
        at sun.security.provider.SecureRandom.engineNextBytes(SecureRandom.java:221)
        - locked <0x00000000e3e90be0> (a sun.security.provider.SecureRandom)
        at java.security.SecureRandom.nextBytes(SecureRandom.java:468)
        - locked <0x00000000e3e910c0> (a java.security.SecureRandom)
        at java.security.SecureRandom.next(SecureRandom.java:491)
        at java.util.Random.nextInt(Random.java:329)
        at org.apache.catalina.util.SessionIdGeneratorBase.createSecureRandom(SessionIdGeneratorBase.java:240)
        at org.apache.catalina.util.SessionIdGeneratorBase.getRandomBytes(SessionIdGeneratorBase.java:174)
        at org.apache.catalina.util.StandardSessionIdGenerator.generateSessionId(StandardSessionIdGenerator.java:34)
        at org.apache.catalina.util.SessionIdGeneratorBase.generateSessionId(SessionIdGeneratorBase.java:167)
        at org.apache.catalina.util.SessionIdGeneratorBase.startInternal(SessionIdGeneratorBase.java:260)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
        - locked <0x00000000e3e90730> (a org.apache.catalina.util.StandardSessionIdGenerator)
        at org.apache.catalina.session.ManagerBase.startInternal(ManagerBase.java:717)
        at org.apache.catalina.session.StandardManager.startInternal(StandardManager.java:352)
        - locked <0x00000000e42eefb0> (a org.apache.catalina.session.StandardManager)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
        - locked <0x00000000e42eefb0> (a org.apache.catalina.session.StandardManager)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5339)
        - locked <0x00000000ed3c6ca0> (a org.apache.catalina.core.StandardContext)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
        - locked <0x00000000ed3c6ca0> (a org.apache.catalina.core.StandardContext)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:753)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:729)
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717)
        at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:974)
        at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1850)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
    
    "Catalina-startStop-1" #14 daemon prio=5 os_prio=0 tid=0x00007f3dc4437000 nid=0x5207 waiting on condition [0x00007f3da16d2000]
       java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000ed3c6fc0> (a java.util.concurrent.FutureTask)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
        at java.util.concurrent.FutureTask.get(FutureTask.java:191)
        at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:766)
        at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:436)
        at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1580)
        at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:322)
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:95)
        at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
        at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:388)
        - locked <0x00000000ed03ec38> (a org.apache.catalina.core.StandardHost)
        at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:333)
        - locked <0x00000000ed03ec38> (a org.apache.catalina.core.StandardHost)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:960)
        - locked <0x00000000ed03ec38> (a org.apache.catalina.core.StandardHost)
        at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:871)
        - locked <0x00000000ed03ec38> (a org.apache.catalina.core.StandardHost)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
        - locked <0x00000000ed03ec38> (a org.apache.catalina.core.StandardHost)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
    
    "NioBlockingSelector.BlockPoller-2" #13 daemon prio=5 os_prio=0 tid=0x00007f3dc4429800 nid=0x5206 runnable [0x00007f3da17d4000]
       java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
        at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
        at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
        at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
        - locked <0x00000000ed3c75a8> (a sun.nio.ch.Util$2)
        - locked <0x00000000ed3c75b8> (a java.util.Collections$UnmodifiableSet)
        - locked <0x00000000ed3c7560> (a sun.nio.ch.EPollSelectorImpl)
        at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
        at org.apache.tomcat.util.net.NioBlockingSelector$BlockPoller.run(NioBlockingSelector.java:301)
    
    "NioBlockingSelector.BlockPoller-1" #12 daemon prio=5 os_prio=0 tid=0x00007f3dc440e800 nid=0x5205 runnable [0x00007f3da18d5000]
       java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
        at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
        at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
        at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
        - locked <0x00000000ed3c77e0> (a sun.nio.ch.Util$2)
        - locked <0x00000000ed3c77f0> (a java.util.Collections$UnmodifiableSet)
        - locked <0x00000000ed3c7798> (a sun.nio.ch.EPollSelectorImpl)
        at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
        at org.apache.tomcat.util.net.NioBlockingSelector$BlockPoller.run(NioBlockingSelector.java:301)
    
    "GC Daemon" #11 daemon prio=2 os_prio=0 tid=0x00007f3dc4356800 nid=0x5204 in Object.wait() [0x00007f3dc81a0000]
       java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000ed0d57f0> (a sun.misc.GC$LatencyLock)
        at sun.misc.GC$Daemon.run(GC.java:117)
        - locked <0x00000000ed0d57f0> (a sun.misc.GC$LatencyLock)
    
    "AsyncFileHandlerWriter-789451787" #10 daemon prio=5 os_prio=0 tid=0x00007f3dc4105000 nid=0x5203 waiting on condition [0x00007f3dc8338000]
       java.lang.Thread.State: TIMED_WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000ecec1210> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
        at java.util.concurrent.LinkedBlockingDeque.pollFirst(LinkedBlockingDeque.java:522)
        at java.util.concurrent.LinkedBlockingDeque.poll(LinkedBlockingDeque.java:684)
        at org.apache.juli.AsyncFileHandler$LoggerThread.run(AsyncFileHandler.java:153)
    
    "Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007f3dc40b3800 nid=0x5201 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f3dc40b0800 nid=0x5200 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f3dc40ae800 nid=0x51ff waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f3dc40ad000 nid=0x51fe runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f3dc407a000 nid=0x51fd in Object.wait() [0x00007f3dc893e000]
       java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000ecec2320> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
        - locked <0x00000000ecec2320> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
    
    "Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f3dc4075000 nid=0x51fc in Object.wait() [0x00007f3dc8a3f000]
       java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000000ecec24d8> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x00000000ecec24d8> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
    
    "main" #1 prio=5 os_prio=0 tid=0x00007f3dc4009000 nid=0x51fa waiting on condition [0x00007f3dcc417000]
       java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000ed3c7340> (a java.util.concurrent.FutureTask)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
        at java.util.concurrent.FutureTask.get(FutureTask.java:191)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:943)
        - locked <0x00000000ecfb7038> (a org.apache.catalina.core.StandardEngine)
        at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
        - locked <0x00000000ecfb7038> (a org.apache.catalina.core.StandardEngine)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
        - locked <0x00000000ecfb7038> (a org.apache.catalina.core.StandardEngine)
        at org.apache.catalina.core.StandardService.startInternal(StandardService.java:441)
        - locked <0x00000000ecfb7038> (a org.apache.catalina.core.StandardEngine)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
        - locked <0x00000000ecfa2330> (a org.apache.catalina.core.StandardService)
        at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:789)
        - locked <0x00000000ecf4e258> (a java.lang.Object)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
        - locked <0x00000000ecf1c578> (a org.apache.catalina.core.StandardServer)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:641)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:349)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:483)
    
    "VM Thread" os_prio=0 tid=0x00007f3dc406d800 nid=0x51fb runnable
    
    "VM Periodic Task Thread" os_prio=0 tid=0x00007f3dc40b7000 nid=0x5202 waiting on condition
    
    JNI global references: 59
    
    • localhost-startStop-1:线程名
    • daemon:后台线程
    • prio:优先级
    • os_prio:系统优先级
    • tid:线程id
    • nid:操作系统id
    • java.lang.Thread.State:线程状态;NEW-线程尚未启动, RUNNABLE- 线程运行中,BLOCKED-等待一个锁, WAITINH-等待另一个线程, TIMED_WAITING-限时等待另一个线程, TERMINATED-已退出
    5.1 实战死循环
    import java.util.ArrayList;
    import java.util.List;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class CpuController {
        
        /**
         * 死循环
         * */
        @RequestMapping("/loop")
        public List<Long> loop(){
            String data = "{\"data\":[{\"partnerid\":]";
            return getPartneridsFromJson(data);
        }
        
        private Object lock1 = new Object();
        private Object lock2 = new Object();
        
        /**
         * 死锁
         * */
        @RequestMapping("/deadlock")
        public String deadlock(){
            new Thread(()->{
                synchronized(lock1) {
                    try {Thread.sleep(1000);}catch(Exception e) {}
                    synchronized(lock2) {
                        System.out.println("Thread1 over");
                    }
                }
            }) .start();
            new Thread(()->{
                synchronized(lock2) {
                    try {Thread.sleep(1000);}catch(Exception e) {}
                    synchronized(lock1) {
                        System.out.println("Thread2 over");
                    }
                }
            }) .start();
            return "deadlock";
        }
        public static List<Long> getPartneridsFromJson(String data){  
            //{\"data\":[{\"partnerid\":982,\"count\":\"10000\",\"cityid\":\"11\"},{\"partnerid\":983,\"count\":\"10000\",\"cityid\":\"11\"},{\"partnerid\":984,\"count\":\"10000\",\"cityid\":\"11\"}]}  
            //上面是正常的数据  
            List<Long> list = new ArrayList<Long>(2);  
            if(data == null || data.length() <= 0){  
                return list;  
            }      
            int datapos = data.indexOf("data");  
            if(datapos < 0){  
                return list;  
            }  
            int leftBracket = data.indexOf("[",datapos);  
            int rightBracket= data.indexOf("]",datapos);  
            if(leftBracket < 0 || rightBracket < 0){  
                return list;  
            }  
            String partners = data.substring(leftBracket+1,rightBracket);  
            if(partners == null || partners.length() <= 0){  
                return list;  
            }  
            while(partners!=null && partners.length() > 0){  
                int idpos = partners.indexOf("partnerid");  
                if(idpos < 0){  
                    break;  
                }  
                int colonpos = partners.indexOf(":",idpos);  
                int commapos = partners.indexOf(",",idpos);  
                if(colonpos < 0 || commapos < 0){  
                    //partners = partners.substring(idpos+"partnerid".length());//1  
                    continue;
                }  
                String pid = partners.substring(colonpos+1,commapos);  
                if(pid == null || pid.length() <= 0){  
                    //partners = partners.substring(idpos+"partnerid".length());//2  
                    continue;
                }  
                try{  
                    list.add(Long.parseLong(pid));  
                }catch(Exception e){  
                    //do nothing  
                }  
                partners = partners.substring(commapos);  
            }  
            return list;  
        }  
        
    }
    

    访问/loop端点三次,然后使用top命令:


    #导出线程堆栈
    $ jstack 7930 > 7930.txt
    #打印该进程下的线程
    $ top -p 7930 -H
    
    #将十进制线程id转换为16进制
    $ printf "%x" 8247
    2037
    

    然后在导出的7930.txt文件中找到2037


    死循环

    访问/loop端点,制造死循环,使用jstack命令导出线程堆栈信息:


    死锁

    最后一行已提示:Found 1 deadlock

    相关资料:
    jdk8工具集
    https://docs.oracle.com/javase/8/docs/technotes/tools/unix/index.html
    Troubleshooting
    https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/
    jps
    https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jps.html
    jinfo
    https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jinfo.html
    jstat
    https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html
    jmap:
    https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jmap.html
    mat:
    http://www.eclipse.org/mat/downloads.php
    jstack:
    https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstack.html
    java线程的状态
    https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr034.html
    java线程状态转化:
    https://mp.weixin.qq.com/s/GsxeFM7QWuR--Kbpb7At2w
    死循环导致CPU负载高
    https://blog.csdn.net/goldenfish1919/article/details/8755378
    正则表达式导致死循环:
    https://blog.csdn.net/goldenfish1919/article/details/49123787

    相关文章

      网友评论

        本文标题:JVM性能调优指南(一)

        本文链接:https://www.haomeiwen.com/subject/uemnwftx.html