zoukankan      html  css  js  c++  java
  • Java常用命令行工具

    常用的Java命令行工具的使用梳理,方便以后线上问题排查处理.

    示例使用的虚拟机版本(JVM自带命令行工具在bin目录下)

    [root@localhost ~]# java -version
    java version "1.8.0_121"
    Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
    Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
    [root@localhost ~]# which java
    /usr/local/jdk1.8.0_121/bin/java
    [root@localhost ~]# ls /usr/local/jdk1.8.0_121/bin/
    appletviewer  jarsigner       javah         jcmd      jhat   jmc.ini     jstat         orbd        rmiregistry  unpack200
    ControlPanel  java            javap         jconsole  jinfo  jps         jstatd        pack200     schemagen    wsgen
    extcheck      javac           javapackager  jcontrol  jjs    jrunscript  jvisualvm     policytool  serialver    wsimport
    idlj          javadoc         java-rmi.cgi  jdb       jmap   jsadebugd   keytool       rmic        servertool   xjc
    jar           javafxpackager  javaws        jdeps     jmc    jstack      native2ascii  rmid        tnameserv
    

    常用Java命令行工具

    • javap : java字节码信息查看工具
    • jps : java虚拟机进程信息工具
    • jinfo : java虚拟机进程配置信息工具
    • jstat : java虚拟机进程统计信息监控工具
    • jstack : java虚拟机进程堆栈跟踪工具, 制作线程Dump
    • jmap : java虚拟机进程堆内存映射,制作堆Dump
    • jhat : java虚拟机堆转储快照分析工具
    • jconsole : 用于提供JVM活动的图形化视图,包括线程的使用、类的使用和GC活动.
    • jvisualvm: 监控JVM的GUI工具,可用来剖析运行的应用,分析JVM堆转储.

    术语认知

    Java Dump介绍

    Java虚拟机的运行时快照.将Java虚拟机运行时的状态和信息保存到文件, 用于补足传统Bug分析手段的不足,可在任何Java环境使用; 信息量充足;针对非功能正确性的Bug(像多线程幵发、内存泄漏)

    • ThreadDump : 包含所有线程的运行状态.纯文本格式
    • HeapDump: 包含线程Dump,幵包含所有堆对象的状态,二进制格式.

    制作Java Dump

    使用Java虚拟机配置

    配置jvm参数 -XX:+HeapDumpOnOutOfMemoryError 让虚拟机在OOM异常出现之后自动生成dump文件.
    配置jvm参数 -XX:+HeapDumpOnCtrlBreak 使用Ctrl+Break键,让虚拟机生成dump文件.

    使用图形化工具

    使用JDK自带工具: Java VisualVM

    Linux系统下通过kill命令

    Linux系统下通过kill -3 命令发送进程退出信号'吓唬'一下虚拟机,也能拿到dump文件.

    使用Java命令行工具
    • jstack:打印线程的栈信息,制作线程Dump.
    • jmap:打印内存映射,制作堆Dump.

    命令行工具-jps

    jps(Jvm Process Status Tool) 虚拟机进程状态工具, 可以用于查看当前运行的java行程以及相关参数

    jps语法

    [root@localhost ~]# jps -help
    usage: jps [-help]
           jps [-q] [-mlvV] [<hostid>]
    
    Definitions:
        <hostid>:      <hostname>[:<port>]
    

    参数说明

    • -q : 忽略输出的类名、Jar名以及传递给main方法的参数,只输出pid
    • -m : 输出虚拟机进程启动时传递给主类main()方法的参数
    • -l : 输出主类完整的包名和类名,如果进程执行的是jar包,输出jar包路径
    • -v : 输出虚拟机进程启动时jvm参数
    • -V : 输出通过标记的文件传递给JVM的参数(.hotspotrc文件,或者是通过参数-XX:Flags=指定的文件)

    jps示例

    输出Java进程pid
    [root@localhost ~]# jps -q
    3126
    6940
    
    输出主类包名和类名
    [root@localhost ~]# jps -l
    3126 org.apache.catalina.startup.Bootstrap
    6955 sun.tools.jps.Jps
    
    输出进程启动时传递给主类的方法参数
    [root@localhost ~]# jps -m
    3126 Bootstrap start
    6970 Jps -m
    [root@localhost ~]# jps -lm
    3126 org.apache.catalina.startup.Bootstrap start
    6985 sun.tools.jps.Jps -lm
    
    输出通过标记文件传递给Jvm的参数
    [root@localhost ~]# jps -V
    7011 Jps
    3126 Bootstrap
    [root@localhost ~]# jps -lV
    7026 sun.tools.jps.Jps
    3126 org.apache.catalina.startup.Bootstrap
    
    输出进程启动时的jvm参数
    [root@localhost ~]# jps -v
    7073 Jps -Dapplication.home=/usr/local/jdk1.8.0_121 -Xms8m
    3126 Bootstrap -Djava.util.logging.config.file=/usr/local/confluence-6.0.3/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE=32768 -Xms1536m -Xmx2048m -XX:+UseG1GC -Datlassian.plugins.enable.wait=300 -Djava.awt.headless=true -XX:G1ReservePercent=20 -Xloggc:/usr/local/confluence-6.0.3/logs/gc-2017-10-15_16-08-58.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=2M -XX:-PrintGCDetails -XX:+PrintGCDateStamps -XX:-PrintTenuringDistribution -Dhttp.socket.timeout=10 -Djava.endorsed.dirs=/usr/local/confluence-6.0.3/endorsed -Dcatalina.base=/usr/local/confluence-6.0.3 -Dcatalina.home=/usr/local/confluence-6.0.3 -Djava.io.tmpdir=/usr/local/confluence-6.0.3/temp
    [root@localhost ~]# jps -lv
    7088 sun.tools.jps.Jps -Dapplication.home=/usr/local/jdk1.8.0_121 -Xms8m
    3126 org.apache.catalina.startup.Bootstrap -Djava.util.logging.config.file=/usr/local/confluence-6.0.3/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE=32768 -Xms1536m -Xmx2048m -XX:+UseG1GC -Datlassian.plugins.enable.wait=300 -Djava.awt.headless=true -XX:G1ReservePercent=20 -Xloggc:/usr/local/confluence-6.0.3/logs/gc-2017-10-15_16-08-58.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=2M -XX:-PrintGCDetails -XX:+PrintGCDateStamps -XX:-PrintTenuringDistribution -Dhttp.socket.timeout=10 -Djava.endorsed.dirs=/usr/local/confluence-6.0.3/endorsed -Dcatalina.base=/usr/local/confluence-6.0.3 -Dcatalina.home=/usr/local/confluence-6.0.3 -Djava.io.tmpdir=/usr/local/confluence-6.0.3/temp
    [root@localhost ~]# jps -lmv
    3126 org.apache.catalina.startup.Bootstrap start -Djava.util.logging.config.file=/usr/local/confluence-6.0.3/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE=32768 -Xms1536m -Xmx2048m -XX:+UseG1GC -Datlassian.plugins.enable.wait=300 -Djava.awt.headless=true -XX:G1ReservePercent=20 -Xloggc:/usr/local/confluence-6.0.3/logs/gc-2017-10-15_16-08-58.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=2M -XX:-PrintGCDetails -XX:+PrintGCDateStamps -XX:-PrintTenuringDistribution -Dhttp.socket.timeout=10 -Djava.endorsed.dirs=/usr/local/confluence-6.0.3/endorsed -Dcatalina.base=/usr/local/confluence-6.0.3 -Dcatalina.home=/usr/local/confluence-6.0.3 -Djava.io.tmpdir=/usr/local/confluence-6.0.3/temp
    7103 sun.tools.jps.Jps -lmv -Dapplication.home=/usr/local/jdk1.8.0_121 -Xms8m
    

    命令行工具-jinfo

    jinfo(Configuration Info for Java) 作用是实时地查看和调整虚拟机各项参数.

    jinfo语法

    [root@localhost ~]# jinfo -help
    Usage:
        jinfo [option] <pid>
            (to connect to running process)
        jinfo [option] <executable <core>
            (to connect to a core file)
        jinfo [option] [server_id@]<remote server IP or hostname>
            (to connect to remote debug server)
    
    where <option> is one of:
        -flag <name>         to print the value of the named VM flag
        -flag [+|-]<name>    to enable or disable the named VM flag
        -flag <name>=<value> to set the named VM flag to the given value
        -flags               to print VM flags
        -sysprops            to print Java system properties
        <no option>          to print both of the above
        -h | -help           to print this help message
    

    jinfo示例

    获取应用进程所有配置信息
    [root@localhost ~]# jps -l
    3126 org.apache.catalina.startup.Bootstrap
    4076 sun.tools.jps.Jps
    [root@localhost ~]# jinfo 3126
    Attaching to process ID 3126, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.121-b13
    Java System Properties:
    
    java.vendor = Oracle Corporation
    sun.java.launcher = SUN_STANDARD
    catalina.base = /usr/local/confluence-6.0.3
    sun.management.compiler = HotSpot 64-Bit Tiered Compilers
    catalina.useNaming = true
    os.name = Linux
    java.util.logging.config.file = /usr/local/confluence-6.0.3/conf/logging.properties
    sun.boot.class.path = /usr/local/jdk1.8.0_121/jre/lib/resources.jar:/usr/local/jdk1.8.0_121/jre/lib/rt.jar:/usr/local/jdk1.8.0_121/jre/lib/sunrsasign.jar:/usr/local/jdk1.8.0_121/jre/lib/jsse.jar:/usr/local/jdk1.8.0_121/jre/lib/jce.jar:/usr/local/jdk1.8.0_121/jre/lib/charsets.jar:/usr/local/jdk1.8.0_121/jre/lib/jfr.jar:/usr/local/jdk1.8.0_121/jre/classes
    java.vm.specification.vendor = Oracle Corporation
    java.runtime.version = 1.8.0_121-b13
    atlassian.plugins.enable.wait = 300
    user.name = root
    shared.loader = 
    tomcat.util.scan.StandardJarScanFilter.jarsToScan = log4j-web*.jar,log4j-taglib*.jar,log4javascript*.jar,slf4j-taglib*.jar
    com.sun.jndi.ldap.connect.pool.protocol = plain ssl
    com.sun.jndi.ldap.connect.pool.authentication = simple
    tomcat.util.buf.StringCache.byte.enabled = true
    user.language = zh
    java.naming.factory.initial = org.apache.naming.java.javaURLContextFactory
    sun.boot.library.path = /usr/local/jdk1.8.0_121/jre/lib/amd64
    atlassian.enable.spring.strong.cache.bean.metadata = true
    jdk.tls.ephemeralDHKeySize = 2048
    java.version = 1.8.0_121
    java.util.logging.manager = org.apache.juli.ClassLoaderLogManager
    user.timezone = Asia/Shanghai
    sun.arch.data.model = 64
    atlassian.enable.spring.strong.cache.bean.metadata.flush = true
    java.endorsed.dirs = /usr/local/confluence-6.0.3/endorsed
    sun.cpu.isalist = 
    sun.jnu.encoding = UTF-8
    file.encoding.pkg = sun.io
    org.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE = 32768
    package.access = sun.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.tomcat.
    file.separator = /
    java.specification.name = Java Platform API Specification
    java.class.version = 52.0
    user.country = CN
    java.home = /usr/local/jdk1.8.0_121/jre
    atlassian.org.osgi.framework.bootdelegation.extra = org.apache.lucene.*
    java.vm.info = mixed mode
    os.version = 3.10.0-514.6.1.el7.x86_64
    com.sun.jndi.ldap.connect.pool.prefsize = 10
    sun.font.fontmanager = sun.awt.X11FontManager
    path.separator = :
    java.vm.version = 25.121-b13
    java.protocol.handler.pkgs = org.apache.catalina.webresources
    java.awt.printerjob = sun.print.PSPrinterJob
    sun.io.unicode.encoding = UnicodeLittle
    sun.java2d.opengl = true
    awt.toolkit = sun.awt.X11.XToolkit
    package.definition = sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.naming.,org.apache.tomcat.
    java.naming.factory.url.pkgs = org.apache.naming
    user.home = /root
    java.specification.vendor = Oracle Corporation
    tomcat.util.scan.StandardJarScanFilter.jarsToSkip = bootstrap.jar,commons-daemon.jar,tomcat-juli.jar,annotations-api.jar,el-api.jar,jsp-api.jar,servlet-api.jar,websocket-api.jar,catalina.jar,catalina-ant.jar,catalina-ha.jar,catalina-storeconfig.jar,catalina-tribes.jar,jasper.jar,jasper-el.jar,ecj-*.jar,tomcat-api.jar,tomcat-util.jar,tomcat-util-scan.jar,tomcat-coyote.jar,tomcat-dbcp.jar,tomcat-jni.jar,tomcat-websocket.jar,tomcat-i18n-en.jar,tomcat-i18n-es.jar,tomcat-i18n-fr.jar,tomcat-i18n-ja.jar,tomcat-juli-adapters.jar,catalina-jmx-remote.jar,catalina-ws.jar,tomcat-jdbc.jar,tools.jar,commons-beanutils*.jar,commons-codec*.jar,commons-collections*.jar,commons-dbcp*.jar,commons-digester*.jar,commons-fileupload*.jar,commons-httpclient*.jar,commons-io*.jar,commons-lang*.jar,commons-logging*.jar,commons-math*.jar,commons-pool*.jar,jstl.jar,taglibs-standard-spec-*.jar,geronimo-spec-jaxrpc*.jar,wsdl4j*.jar,ant.jar,ant-junit*.jar,aspectj*.jar,jmx.jar,h2*.jar,hibernate*.jar,httpclient*.jar,jmx-tools.jar,jta*.jar,log4j*.jar,mail*.jar,slf4j*.jar,xercesImpl.jar,xmlParserAPIs.jar,xml-apis.jar,junit.jar,junit-*.jar,ant-launcher.jar,cobertura-*.jar,asm-*.jar,dom4j-*.jar,icu4j-*.jar,jaxen-*.jar,jdom-*.jar,jetty-*.jar,oro-*.jar,servlet-api-*.jar,tagsoup-*.jar,xmlParserAPIs-*.jar,xom-*.jar
    java.library.path = /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
    java.vendor.url = http://java.oracle.com/
    java.vm.vendor = Oracle Corporation
    common.loader = "${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"
    java.runtime.name = Java(TM) SE Runtime Environment
    sun.java.command = org.apache.catalina.startup.Bootstrap start
    java.class.path = /usr/local/confluence-6.0.3/bin/bootstrap.jar:/usr/local/confluence-6.0.3/bin/tomcat-juli.jar
    hibernate.bytecode.use_reflection_optimizer = true
    com.sun.jndi.ldap.connect.pool.maxsize = 0
    java.vm.specification.name = Java Virtual Machine Specification
    java.vm.specification.version = 1.8
    catalina.home = /usr/local/confluence-6.0.3
    sun.cpu.endian = little
    sun.os.patch.level = unknown
    java.awt.headless = true
    java.io.tmpdir = /usr/local/confluence-6.0.3/temp
    java.vendor.url.bug = http://bugreport.sun.com/bugreport/
    server.loader = 
    os.arch = amd64
    java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
    java.ext.dirs = /usr/local/jdk1.8.0_121/jre/lib/ext:/usr/java/packages/lib/ext
    user.dir = /
    com.sun.jndi.ldap.connect.pool.initsize = 1
    line.separator = 
    
    java.vm.name = Java HotSpot(TM) 64-Bit Server VM
    file.encoding = UTF-8
    com.sun.jndi.ldap.connect.pool.timeout = 30000
    http.socket.timeout = 10
    java.specification.version = 1.8
    plugin.webresource.javascript.try.catch.wrapping = true
    
    VM Flags:
    Non-default VM flags: -XX:CICompilerCount=3 -XX:ConcGCThreads=1 -XX:G1HeapRegionSize=1048576 -XX:G1ReservePercent=20 -XX:GCLogFileSize=2097152 -XX:InitialHeapSize=1610612736 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=2147483648 -XX:MaxNewSize=1287651328 -XX:MinHeapDeltaBytes=1048576 -XX:NumberOfGCLogFiles=5 -XX:+PrintGC -XX:+PrintGCDateStamps -XX:-PrintGCDetails -XX:+PrintGCTimeStamps -XX:-PrintTenuringDistribution -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseG1GC -XX:+UseGCLogFileRotation 
    Command line:  -Djava.util.logging.config.file=/usr/local/confluence-6.0.3/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE=32768 -Xms1536m -Xmx2048m -XX:+UseG1GC -Datlassian.plugins.enable.wait=300 -Djava.awt.headless=true -XX:G1ReservePercent=20 -Xloggc:/usr/local/confluence-6.0.3/logs/gc-2017-10-15_16-08-58.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=2M -XX:-PrintGCDetails -XX:+PrintGCDateStamps -XX:-PrintTenuringDistribution -Dhttp.socket.timeout=10 -Djava.endorsed.dirs=/usr/local/confluence-6.0.3/endorsed -Dcatalina.base=/usr/local/confluence-6.0.3 -Dcatalina.home=/usr/local/confluence-6.0.3 -Djava.io.tmpdir=/usr/local/confluence-6.0.3/temp
    
    获取应用进程的命令行参数信息
    [root@localhost ~]# jinfo -flags 3126
    Attaching to process ID 3126, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.121-b13
    Non-default VM flags: -XX:CICompilerCount=3 -XX:ConcGCThreads=1 -XX:G1HeapRegionSize=1048576 -XX:G1ReservePercent=20 -XX:GCLogFileSize=2097152 -XX:InitialHeapSize=1610612736 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=2147483648 -XX:MaxNewSize=1287651328 -XX:MinHeapDeltaBytes=1048576 -XX:NumberOfGCLogFiles=5 -XX:+PrintGC -XX:+PrintGCDateStamps -XX:-PrintGCDetails -XX:+PrintGCTimeStamps -XX:-PrintTenuringDistribution -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseG1GC -XX:+UseGCLogFileRotation 
    Command line:  -Djava.util.logging.config.file=/usr/local/confluence-6.0.3/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Dorg.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE=32768 -Xms1536m -Xmx2048m -XX:+UseG1GC -Datlassian.plugins.enable.wait=300 -Djava.awt.headless=true -XX:G1ReservePercent=20 -Xloggc:/usr/local/confluence-6.0.3/logs/gc-2017-10-15_16-08-58.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=2M -XX:-PrintGCDetails -XX:+PrintGCDateStamps -XX:-PrintTenuringDistribution -Dhttp.socket.timeout=10 -Djava.endorsed.dirs=/usr/local/confluence-6.0.3/endorsed -Dcatalina.base=/usr/local/confluence-6.0.3 -Dcatalina.home=/usr/local/confluence-6.0.3 -Djava.io.tmpdir=/usr/local/confluence-6.0.3/temp
    [root@localhost ~]#
    [root@localhost ~]# jinfo -flag PrintGCDetails 3126
    -XX:-PrintGCDetails
    [root@localhost ~]# jinfo -flag MaxHeapSize 3126
    -XX:MaxHeapSize=2147483648
    
    打印应用进程的系统参数信息(System.getProperties())
    [root@localhost ~]# jinfo -sysprops 3126
    Attaching to process ID 3126, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.121-b13
    java.vendor = Oracle Corporation
    sun.java.launcher = SUN_STANDARD
    catalina.base = /usr/local/confluence-6.0.3
    sun.management.compiler = HotSpot 64-Bit Tiered Compilers
    catalina.useNaming = true
    os.name = Linux
    java.util.logging.config.file = /usr/local/confluence-6.0.3/conf/logging.properties
    sun.boot.class.path = /usr/local/jdk1.8.0_121/jre/lib/resources.jar:/usr/local/jdk1.8.0_121/jre/lib/rt.jar:/usr/local/jdk1.8.0_121/jre/lib/sunrsasign.jar:/usr/local/jdk1.8.0_121/jre/lib/jsse.jar:/usr/local/jdk1.8.0_121/jre/lib/jce.jar:/usr/local/jdk1.8.0_121/jre/lib/charsets.jar:/usr/local/jdk1.8.0_121/jre/lib/jfr.jar:/usr/local/jdk1.8.0_121/jre/classes
    java.vm.specification.vendor = Oracle Corporation
    java.runtime.version = 1.8.0_121-b13
    atlassian.plugins.enable.wait = 300
    user.name = root
    shared.loader = 
    tomcat.util.scan.StandardJarScanFilter.jarsToScan = log4j-web*.jar,log4j-taglib*.jar,log4javascript*.jar,slf4j-taglib*.jar
    com.sun.jndi.ldap.connect.pool.protocol = plain ssl
    com.sun.jndi.ldap.connect.pool.authentication = simple
    tomcat.util.buf.StringCache.byte.enabled = true
    user.language = zh
    java.naming.factory.initial = org.apache.naming.java.javaURLContextFactory
    sun.boot.library.path = /usr/local/jdk1.8.0_121/jre/lib/amd64
    atlassian.enable.spring.strong.cache.bean.metadata = true
    jdk.tls.ephemeralDHKeySize = 2048
    java.version = 1.8.0_121
    java.util.logging.manager = org.apache.juli.ClassLoaderLogManager
    user.timezone = Asia/Shanghai
    sun.arch.data.model = 64
    atlassian.enable.spring.strong.cache.bean.metadata.flush = true
    java.endorsed.dirs = /usr/local/confluence-6.0.3/endorsed
    sun.cpu.isalist = 
    sun.jnu.encoding = UTF-8
    file.encoding.pkg = sun.io
    org.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE = 32768
    package.access = sun.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.tomcat.
    file.separator = /
    java.specification.name = Java Platform API Specification
    java.class.version = 52.0
    user.country = CN
    java.home = /usr/local/jdk1.8.0_121/jre
    atlassian.org.osgi.framework.bootdelegation.extra = org.apache.lucene.*
    java.vm.info = mixed mode
    os.version = 3.10.0-514.6.1.el7.x86_64
    com.sun.jndi.ldap.connect.pool.prefsize = 10
    sun.font.fontmanager = sun.awt.X11FontManager
    path.separator = :
    java.vm.version = 25.121-b13
    java.protocol.handler.pkgs = org.apache.catalina.webresources
    java.awt.printerjob = sun.print.PSPrinterJob
    sun.io.unicode.encoding = UnicodeLittle
    sun.java2d.opengl = true
    awt.toolkit = sun.awt.X11.XToolkit
    package.definition = sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.naming.,org.apache.tomcat.
    java.naming.factory.url.pkgs = org.apache.naming
    user.home = /root
    java.specification.vendor = Oracle Corporation
    tomcat.util.scan.StandardJarScanFilter.jarsToSkip = bootstrap.jar,commons-daemon.jar,tomcat-juli.jar,annotations-api.jar,el-api.jar,jsp-api.jar,servlet-api.jar,websocket-api.jar,catalina.jar,catalina-ant.jar,catalina-ha.jar,catalina-storeconfig.jar,catalina-tribes.jar,jasper.jar,jasper-el.jar,ecj-*.jar,tomcat-api.jar,tomcat-util.jar,tomcat-util-scan.jar,tomcat-coyote.jar,tomcat-dbcp.jar,tomcat-jni.jar,tomcat-websocket.jar,tomcat-i18n-en.jar,tomcat-i18n-es.jar,tomcat-i18n-fr.jar,tomcat-i18n-ja.jar,tomcat-juli-adapters.jar,catalina-jmx-remote.jar,catalina-ws.jar,tomcat-jdbc.jar,tools.jar,commons-beanutils*.jar,commons-codec*.jar,commons-collections*.jar,commons-dbcp*.jar,commons-digester*.jar,commons-fileupload*.jar,commons-httpclient*.jar,commons-io*.jar,commons-lang*.jar,commons-logging*.jar,commons-math*.jar,commons-pool*.jar,jstl.jar,taglibs-standard-spec-*.jar,geronimo-spec-jaxrpc*.jar,wsdl4j*.jar,ant.jar,ant-junit*.jar,aspectj*.jar,jmx.jar,h2*.jar,hibernate*.jar,httpclient*.jar,jmx-tools.jar,jta*.jar,log4j*.jar,mail*.jar,slf4j*.jar,xercesImpl.jar,xmlParserAPIs.jar,xml-apis.jar,junit.jar,junit-*.jar,ant-launcher.jar,cobertura-*.jar,asm-*.jar,dom4j-*.jar,icu4j-*.jar,jaxen-*.jar,jdom-*.jar,jetty-*.jar,oro-*.jar,servlet-api-*.jar,tagsoup-*.jar,xmlParserAPIs-*.jar,xom-*.jar
    java.library.path = /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
    java.vendor.url = http://java.oracle.com/
    java.vm.vendor = Oracle Corporation
    common.loader = "${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"
    java.runtime.name = Java(TM) SE Runtime Environment
    sun.java.command = org.apache.catalina.startup.Bootstrap start
    java.class.path = /usr/local/confluence-6.0.3/bin/bootstrap.jar:/usr/local/confluence-6.0.3/bin/tomcat-juli.jar
    hibernate.bytecode.use_reflection_optimizer = true
    com.sun.jndi.ldap.connect.pool.maxsize = 0
    java.vm.specification.name = Java Virtual Machine Specification
    java.vm.specification.version = 1.8
    catalina.home = /usr/local/confluence-6.0.3
    sun.cpu.endian = little
    sun.os.patch.level = unknown
    java.awt.headless = true
    java.io.tmpdir = /usr/local/confluence-6.0.3/temp
    java.vendor.url.bug = http://bugreport.sun.com/bugreport/
    server.loader = 
    os.arch = amd64
    java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
    java.ext.dirs = /usr/local/jdk1.8.0_121/jre/lib/ext:/usr/java/packages/lib/ext
    user.dir = /
    com.sun.jndi.ldap.connect.pool.initsize = 1
    line.separator = 
    
    java.vm.name = Java HotSpot(TM) 64-Bit Server VM
    file.encoding = UTF-8
    com.sun.jndi.ldap.connect.pool.timeout = 30000
    http.socket.timeout = 10
    java.specification.version = 1.8
    plugin.webresource.javascript.try.catch.wrapping = true
    

    命令行工具-javap

    javap是jdk自带的一个工具,可以对代码反编译,也可以查看java编译器生成的字节码.

    javap语法

    [root@localhost ~]# javap -help
    用法: javap <options> <classes>
    其中, 可能的选项包括:
      -help  --help  -?        输出此用法消息
      -version                 版本信息
      -v  -verbose             输出附加信息
      -l                       输出行号和本地变量表
      -public                  仅显示公共类和成员
      -protected               显示受保护的/公共类和成员
      -package                 显示程序包/受保护的/公共类
                               和成员 (默认)
      -p  -private             显示所有类和成员
      -c                       对代码进行反汇编
      -s                       输出内部类型签名
      -sysinfo                 显示正在处理的类的
                               系统信息 (路径, 大小, 日期, MD5 散列)
      -constants               显示最终常量
      -classpath <path>        指定查找用户类文件的位置
      -cp <path>               指定查找用户类文件的位置
      -bootclasspath <path>    覆盖引导类文件的位置
    

    javap示例

    javap命令分解一个class文件,它根据options来决定到底输出什么.如果没有使用options,那么javap将会输出包,类里的protected和public域以及类里的所有方法.javap将会把它们输出在标准输出上

    示例代码
    [root@localhost ~]# cat ThreadDumpTest.java 
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class ThreadDumpTest {
    
        public static void main(String[] args) {
    
            ExecutorService executor = Executors.newFixedThreadPool(3);
            for(int i=0; i<5; i++){
                executor.submit(new ThreadPrint("测试线程"+ i));
            }
        }
    
        static class ThreadPrint implements Runnable{
    
            private String name;
    
            private ThreadPrint(String name){
                this.name = name;
            }
    
            @Override
            public void run() {
                Thread thread = Thread.currentThread();
                thread.setName(name);
                int i=0;
                while (true){
                    System.out.println(thread.getName() + "输出" + i++);
                }
            }
        }
    
    }
    
    [root@localhost ~]# javac ThreadDumpTest.java 
    
    javap
    [root@localhost ~]# javap ThreadDumpTest.class 
    Compiled from "ThreadDumpTest.java"
    public class ThreadDumpTest {
      public ThreadDumpTest();
      public static void main(java.lang.String[]);
    }
    
    -version
    [root@localhost ~]# javap -version ThreadDumpTest.class 
    1.8.0_121
    Compiled from "ThreadDumpTest.java"
    public class ThreadDumpTest {
      public ThreadDumpTest();
      public static void main(java.lang.String[]);
    }
    
    -sysinfo
    [root@localhost ~]# javap -sysinfo ThreadDumpTest.class 
    Classfile /root/ThreadDumpTest.class
      Last modified 2017-10-15; size 967 bytes
      MD5 checksum b8dce8aa07d62201b068e47eef31fa75
      Compiled from "ThreadDumpTest.java"
    public class ThreadDumpTest {
      public ThreadDumpTest();
      public static void main(java.lang.String[]);
    }
    
    -constants
    [root@localhost ~]# javap -constants ThreadDumpTest.class 
    Compiled from "ThreadDumpTest.java"
    public class ThreadDumpTest {
      public ThreadDumpTest();
      public static void main(java.lang.String[]);
    }
    
    -l
    [root@localhost ~]# javap -l ThreadDumpTest.class 
    Compiled from "ThreadDumpTest.java"
    public class ThreadDumpTest {
      public ThreadDumpTest();
        LineNumberTable:
          line 4: 0
    
      public static void main(java.lang.String[]);
        LineNumberTable:
          line 8: 0
          line 9: 5
          line 10: 12
          line 9: 46
          line 12: 52
    }
    
    -c
    [root@localhost ~]# javap -c ThreadDumpTest.class 
    Compiled from "ThreadDumpTest.java"
    public class ThreadDumpTest {
      public ThreadDumpTest();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: iconst_3
           1: invokestatic  #2                  // Method java/util/concurrent/Executors.newFixedThreadPool:(I)Ljava/util/concurrent/ExecutorService;
           4: astore_1
           5: iconst_0
           6: istore_2
           7: iload_2
           8: iconst_5
           9: if_icmpge     52
          12: aload_1
          13: new           #3                  // class ThreadDumpTest$ThreadPrint
          16: dup
          17: new           #4                  // class java/lang/StringBuilder
          20: dup
          21: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
          24: ldc           #6                  // String 测试线程
          26: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          29: iload_2
          30: invokevirtual #8                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
          33: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          36: aconst_null
          37: invokespecial #10                 // Method ThreadDumpTest$ThreadPrint."<init>":(Ljava/lang/String;LThreadDumpTest$1;)V
          40: invokeinterface #11,  2           // InterfaceMethod java/util/concurrent/ExecutorService.submit:(Ljava/lang/Runnable;)Ljava/util/concurrent/Future;
          45: pop
          46: iinc          2, 1
          49: goto          7
          52: return
    }
    
    -s
    [root@localhost ~]# javap -s ThreadDumpTest.class 
    Compiled from "ThreadDumpTest.java"
    public class ThreadDumpTest {
      public ThreadDumpTest();
        descriptor: ()V
    
      public static void main(java.lang.String[]);
        descriptor: ([Ljava/lang/String;)V
    }
    
    -package & -public & -protected & -private
    [root@localhost ~]# javap -package ThreadDumpTest.class 
    Compiled from "ThreadDumpTest.java"
    public class ThreadDumpTest {
      public ThreadDumpTest();
      public static void main(java.lang.String[]);
    }
    [root@localhost ~]# javap -public ThreadDumpTest.class 
    Compiled from "ThreadDumpTest.java"
    public class ThreadDumpTest {
      public ThreadDumpTest();
      public static void main(java.lang.String[]);
    }
    [root@localhost ~]# javap -protected ThreadDumpTest.class 
    Compiled from "ThreadDumpTest.java"
    public class ThreadDumpTest {
      public ThreadDumpTest();
      public static void main(java.lang.String[]);
    }
    [root@localhost ~]# javap -private ThreadDumpTest.class 
    Compiled from "ThreadDumpTest.java"
    public class ThreadDumpTest {
      public ThreadDumpTest();
      public static void main(java.lang.String[]);
    }
    
    -v
    [root@localhost ~]# javap -v ThreadDumpTest.class 
    Classfile /root/ThreadDumpTest.class
      Last modified 2017-10-15; size 967 bytes
      MD5 checksum b8dce8aa07d62201b068e47eef31fa75
      Compiled from "ThreadDumpTest.java"
    public class ThreadDumpTest
      minor version: 0
      major version: 52
      flags: ACC_PUBLIC, ACC_SUPER
    Constant pool:
       #1 = Methodref          #13.#27        // java/lang/Object."<init>":()V
       #2 = Methodref          #28.#29        // java/util/concurrent/Executors.newFixedThreadPool:(I)Ljava/util/concurrent/ExecutorService;
       #3 = Class              #30            // ThreadDumpTest$ThreadPrint
       #4 = Class              #31            // java/lang/StringBuilder
       #5 = Methodref          #4.#27         // java/lang/StringBuilder."<init>":()V
       #6 = String             #32            // 测试线程
       #7 = Methodref          #4.#33         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
       #8 = Methodref          #4.#34         // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
       #9 = Methodref          #4.#35         // java/lang/StringBuilder.toString:()Ljava/lang/String;
      #10 = Methodref          #3.#36         // ThreadDumpTest$ThreadPrint."<init>":(Ljava/lang/String;LThreadDumpTest$1;)V
      #11 = InterfaceMethodref #37.#38        // java/util/concurrent/ExecutorService.submit:(Ljava/lang/Runnable;)Ljava/util/concurrent/Future;
      #12 = Class              #39            // ThreadDumpTest
      #13 = Class              #40            // java/lang/Object
      #14 = Class              #41            // ThreadDumpTest$1
      #15 = Utf8               InnerClasses
      #16 = Utf8               ThreadPrint
      #17 = Utf8               <init>
      #18 = Utf8               ()V
      #19 = Utf8               Code
      #20 = Utf8               LineNumberTable
      #21 = Utf8               main
      #22 = Utf8               ([Ljava/lang/String;)V
      #23 = Utf8               StackMapTable
      #24 = Class              #42            // java/util/concurrent/ExecutorService
      #25 = Utf8               SourceFile
      #26 = Utf8               ThreadDumpTest.java
      #27 = NameAndType        #17:#18        // "<init>":()V
      #28 = Class              #43            // java/util/concurrent/Executors
      #29 = NameAndType        #44:#45        // newFixedThreadPool:(I)Ljava/util/concurrent/ExecutorService;
      #30 = Utf8               ThreadDumpTest$ThreadPrint
      #31 = Utf8               java/lang/StringBuilder
      #32 = Utf8               测试线程
      #33 = NameAndType        #46:#47        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      #34 = NameAndType        #46:#48        // append:(I)Ljava/lang/StringBuilder;
      #35 = NameAndType        #49:#50        // toString:()Ljava/lang/String;
      #36 = NameAndType        #17:#51        // "<init>":(Ljava/lang/String;LThreadDumpTest$1;)V
      #37 = Class              #42            // java/util/concurrent/ExecutorService
      #38 = NameAndType        #52:#53        // submit:(Ljava/lang/Runnable;)Ljava/util/concurrent/Future;
      #39 = Utf8               ThreadDumpTest
      #40 = Utf8               java/lang/Object
      #41 = Utf8               ThreadDumpTest$1
      #42 = Utf8               java/util/concurrent/ExecutorService
      #43 = Utf8               java/util/concurrent/Executors
      #44 = Utf8               newFixedThreadPool
      #45 = Utf8               (I)Ljava/util/concurrent/ExecutorService;
      #46 = Utf8               append
      #47 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
      #48 = Utf8               (I)Ljava/lang/StringBuilder;
      #49 = Utf8               toString
      #50 = Utf8               ()Ljava/lang/String;
      #51 = Utf8               (Ljava/lang/String;LThreadDumpTest$1;)V
      #52 = Utf8               submit
      #53 = Utf8               (Ljava/lang/Runnable;)Ljava/util/concurrent/Future;
    {
      public ThreadDumpTest();
        descriptor: ()V
        flags: ACC_PUBLIC
        Code:
          stack=1, locals=1, args_size=1
             0: aload_0
             1: invokespecial #1                  // Method java/lang/Object."<init>":()V
             4: return
          LineNumberTable:
            line 4: 0
    
      public static void main(java.lang.String[]);
        descriptor: ([Ljava/lang/String;)V
        flags: ACC_PUBLIC, ACC_STATIC
        Code:
          stack=5, locals=3, args_size=1
             0: iconst_3
             1: invokestatic  #2                  // Method java/util/concurrent/Executors.newFixedThreadPool:(I)Ljava/util/concurrent/ExecutorService;
             4: astore_1
             5: iconst_0
             6: istore_2
             7: iload_2
             8: iconst_5
             9: if_icmpge     52
            12: aload_1
            13: new           #3                  // class ThreadDumpTest$ThreadPrint
            16: dup
            17: new           #4                  // class java/lang/StringBuilder
            20: dup
            21: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
            24: ldc           #6                  // String 测试线程
            26: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
            29: iload_2
            30: invokevirtual #8                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
            33: invokevirtual #9                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
            36: aconst_null
            37: invokespecial #10                 // Method ThreadDumpTest$ThreadPrint."<init>":(Ljava/lang/String;LThreadDumpTest$1;)V
            40: invokeinterface #11,  2           // InterfaceMethod java/util/concurrent/ExecutorService.submit:(Ljava/lang/Runnable;)Ljava/util/concurrent/Future;
            45: pop
            46: iinc          2, 1
            49: goto          7
            52: return
          LineNumberTable:
            line 8: 0
            line 9: 5
            line 10: 12
            line 9: 46
            line 12: 52
          StackMapTable: number_of_entries = 2
            frame_type = 253 /* append */
              offset_delta = 7
              locals = [ class java/util/concurrent/ExecutorService, int ]
            frame_type = 250 /* chop */
              offset_delta = 44
    }
    SourceFile: "ThreadDumpTest.java"
    InnerClasses:
         static #14; //class ThreadDumpTest$1
         static #16= #3 of #12; //ThreadPrint=class ThreadDumpTest$ThreadPrint of class ThreadDumpTest
    

    命令行工具-jstat

    jstat(JVM Statistics Monitoring Tool) 是用于监视虚拟机各种运行状态信息的命令行工具.它尅显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据.

    jstat语法

    [root@localhost ~]# jstat -help
    Usage: jstat -help|-options
           jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
    
    Definitions:
      <option>      An option reported by the -options option
      <vmid>        Virtual Machine Identifier. A vmid takes the following form:
                         <lvmid>[@<hostname>[:<port>]]
                    Where <lvmid> is the local vm identifier for the target
                    Java virtual machine, typically a process id; <hostname> is
                    the name of the host running the target Java virtual machine;
                    and <port> is the port number for the rmiregistry on the
                    target host. See the jvmstat documentation for a more complete
                    description of the Virtual Machine Identifier.
      <lines>       Number of samples between header lines.
      <interval>    Sampling interval. The following forms are allowed:
                        <n>["ms"|"s"]
                    Where <n> is an integer and the suffix specifies the units as 
                    milliseconds("ms") or seconds("s"). The default units are "ms".
      <count>       Number of samples to take before terminating.
      -J<flag>      Pass <flag> directly to the runtime system.
    [root@localhost ~]# jstat -options
    -class
    -compiler
    -gc
    -gccapacity
    -gccause
    -gcmetacapacity
    -gcnew
    -gcnewcapacity
    -gcold
    -gcoldcapacity
    -gcutil
    -printcompilation
    

    参数说明

    • -class : 监视类装载、卸载数量、总空间以及类装载所耗费的时间.
    • -compiler : 显示编译器编译过的方法、耗时等信息.
    • -gc : 显示Java堆状况、包括Eden区、两个survivor区、老年代、永久代等的容量、已用空间、GC次数以及时间等信息.
    • -gccapacity: 显示VM内存中三代(young,old,perm)对象的使用和占用大小
    • -gcutil : gc统计信息, 输出主要关注已使用空间占总弓箭的百分比
    • -gccause : 与-gcutil基本相同, 会额外输出导致上一次GC产生的原因
    • -gcnew : 显示新生代GC状况
    • -gcnewcapacity : 显示内容与-gcnew相同,输出主要关注使用到的最大最小空间
    • -gcold : 显示老年代GC状况
    • -gcoldcapacity : 显示内容与-gcold相同,输出主要关注使用到的最大最小空间
    • -printcompilation : 当前vm执行的信息

    jstat示例说明

    每2s执行一次查询统计,执行5次gc统计输出
    [root@localhost ~]# jstat -gc 3126 2 5
     S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
     0.0   81920.0  0.0   81920.0 566272.0 136192.0  924672.0   558080.0  224076.0 205898.7 31368.0 26476.7     36    2.526   0      0.000    2.526
     0.0   81920.0  0.0   81920.0 566272.0 136192.0  924672.0   558080.0  224076.0 205898.7 31368.0 26476.7     36    2.526   0      0.000    2.526
     0.0   81920.0  0.0   81920.0 566272.0 136192.0  924672.0   558080.0  224076.0 205898.7 31368.0 26476.7     36    2.526   0      0.000    2.526
     0.0   81920.0  0.0   81920.0 566272.0 136192.0  924672.0   558080.0  224076.0 205898.7 31368.0 26476.7     36    2.526   0      0.000    2.526
     0.0   81920.0  0.0   81920.0 566272.0 136192.0  924672.0   558080.0  224076.0 205898.7 31368.0 26476.7     36    2.526   0      0.000    2.526
    
    -class
    [root@localhost ~]# jstat -class 3126
    Loaded  Bytes  Unloaded  Bytes     Time   
     39652 72532.0       15    70.1      76.55
    
    -compiler
    [root@localhost ~]# jstat -compiler 3126
    Compiled Failed Invalid   Time   FailedType FailedMethod
       28416      5       0   155.87          1 com/mysql/jdbc/AbandonedConnectionCleanupThread run
    
    -gc
    [root@localhost ~]# jstat -gc 3126
     S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
     0.0   87040.0  0.0   87040.0 601088.0 286720.0  884736.0   513536.0  223820.0 205799.4 31368.0 26473.9     35    2.374   0      0.000    2.374
    
    -gccapacity
    [root@localhost ~]# jstat -gccapacity 3126
     NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC 
         0.0 2097152.0 688128.0    0.0 87040.0 601088.0        0.0  2097152.0   884736.0   884736.0      0.0 1241088.0 223820.0      0.0 1048576.0  31368.0     35     0
    
    -gcutil & -gccause
    [root@localhost ~]# jstat -gcutil 3126
      S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   
      0.00 100.00  40.03  58.04  91.95  84.40     35    2.374     0    0.000    2.374
    [root@localhost ~]# jstat -gccause 3126
      S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT    LGCC                 GCC                 
      0.00 100.00  40.03  58.04  91.95  84.40     35    2.374     0    0.000    2.374 G1 Evacuation Pause  No GC 
    

    参数说明

    • S0: 新生代中Survivor space 0区已使用空间的百分比
    • S1: 新生代中Survivor space 1区已使用空间的百分比
    • E: 新生代已使用空间的百分比
    • O: 老年代已使用空间的百分比
    • P: 永久带已使用空间的百分比
    • YGC: 从应用程序启动到当前,发生Yang GC 的次数
    • YGCT: 从应用程序启动到当前,Yang GC所用的时间【单位秒】
    • FGC: 从应用程序启动到当前,发生Full GC的次数
    • FGCT: 从应用程序启动到当前,Full GC所用的时间
    • GCT: 从应用程序启动到当前,用于垃圾回收的总时间【单位秒】
    -gcmetacapacity
    [root@localhost ~]# jstat -gcmetacapacity 3126
       MCMN       MCMX        MC       CCSMN      CCSMX       CCSC     YGC   FGC    FGCT     GCT   
           0.0  1241088.0   223820.0        0.0  1048576.0    31368.0    35     0    0.000    2.374
    
    -gcnew & -gcnewcapacity
    [root@localhost ~]# jstat -gcnew 3126
     S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT  
       0.0 87040.0    0.0 87040.0 15  15 43520.0 601088.0 354304.0     35    2.374
    [root@localhost ~]# jstat -gcnewcapacity 3126
      NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC      YGC   FGC 
           0.0  2097152.0   688128.0      0.0      0.0 2097152.0  87040.0  2097152.0   601088.0    35     0
    
    -gcold & -gcoldcapacity
    [root@localhost ~]# jstat -gcold 3126
       MC       MU      CCSC     CCSU       OC          OU       YGC    FGC    FGCT     GCT   
    223820.0 205799.4  31368.0  26473.9    884736.0    513536.0     35     0    0.000    2.374
    [root@localhost ~]# jstat -gcoldcapacity 3126
       OGCMN       OGCMX        OGC         OC       YGC   FGC    FGCT     GCT   
            0.0   2097152.0    884736.0    884736.0    35     0    0.000    2.374
    

    -printcompilation

    [root@localhost ~]# jstat -printcompilation 3126
    Compiled  Size  Type Method
       28485    305    1 java/util/GregorianCalendar pinDayOfMonth
    [root@localhost ~]# jstat -printcompilation 3126
    Compiled  Size  Type Method
       28486    362    1 java/lang/StringCoding encode
    

    命令行工具-jstack

    jstack(Stack Trace for Java) 命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件), 线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等.
    在实际运行中,往往一次 dump的信息,还不足以确认问题。建议产生三次 dump信息,如果每次 dump都指向同一个问题,我们才确定问题的典型性。

    jstack语法

    [root@localhost ~]# jstack  -help
    Usage:
        jstack [-l] <pid>
            (to connect to running process)
        jstack -F [-m] [-l] <pid>
            (to connect to a hung process)
        jstack [-m] [-l] <executable> <core>
            (to connect to a core file)
        jstack [-m] [-l] [server_id@]<remote server IP or hostname>
            (to connect to a remote debug server)
    
    Options:
        -F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)
        -m  to print both java and native frames (mixed mode)
        -l  long listing. Prints additional information about locks
        -h or -help to print this help message
    

    参数说明

    • _F : 当正常输出的请求不被响应时,强制输出线程堆栈
    • -l : 长列表,打印关于锁的附加信息
    • -m : 打印java和native方法(c/c++)的堆栈信息

    jstack示例

    使用jstack查看线程堆栈
    [root@localhost ~]# jstack -l 3126
    2017-10-15 20:16:00
    Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode):
    
    "Attach Listener" #171 daemon prio=9 os_prio=0 tid=0x00007feab0561800 nid=0x10d4 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
       Locked ownable synchronizers:
        - None
    
    "lucene-tracked-searchers-pruner-pool-19-thread-1" #170 prio=5 os_prio=0 tid=0x00007feac483d000 nid=0xdb9 waiting on condition [0x00007fea64670000]
       java.lang.Thread.State: TIMED_WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x000000009794bb68> (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.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
        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)
    
       Locked ownable synchronizers:
        - None
    
    "SupportHealthCheckThread-8" #169 daemon prio=5 os_prio=0 tid=0x00007feaa03cc800 nid=0xdb8 waiting on condition [0x00007fea63b65000]
       java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x000000008dc7bc18> (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)
    
       Locked ownable synchronizers:
        - None
    
    使用jstack分析问题代码

    示例展示使用Jstack查看CPU导致CPU使用率过高的问题代码

    查看CPU使用率比较高的进程
    [root@localhost ~]# top
    
    top - 21:06:30 up  4:58,  3 users,  load average: 0.59, 0.17, 0.09
    Tasks: 185 total,   3 running, 182 sleeping,   0 stopped,   0 zombie
    %Cpu(s): 11.7 us, 27.6 sy,  0.0 ni, 60.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
    KiB Mem :  7874196 total,  6227236 free,   855436 used,   791524 buff/cache
    KiB Swap:  8126460 total,  8126460 free,        0 used.  6712744 avail Mem 
    
      PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                        
    13176 root      20   0 4643776  60552  11976 S  83.3  0.8   0:14.11 java                                                
    13047 root      20   0  151508   6856   3972 R  77.8  0.1   0:52.33 sshd                                                
      320 root      20   0       0      0      0 S  38.9  0.0   0:01.67 kworker/1:2                                         
      792 root      20   0    4368    588    496 S   5.6  0.0   0:02.37 rngd                                                
    13202 root      20   0  157708   2300   1564 R   5.6  0.0   0:00.11 top                                                 
        1 root      20   0  128092   6700   3948 S   0.0  0.1   0:01.97 systemd                                             
        2 root      20   0       0      0      0 S   0.0  0.0   0:00.01 kthreadd                                            
        3 root      20   0       0      0      0 S   0.0  0.0   0:00.02 ksoftirqd/0                                         
        5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H                                        
        7 root      rt   0       0      0      0 S   0.0  0.0   0:00.01 migration/0                                         
        8 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcu_bh                                              
        9 root      20   0       0      0      0 S   0.0  0.0   0:13.28 rcu_sched                                           
       10 root      rt   0       0      0      0 S   0.0  0.0   0:00.08 watchdog/0                                          
       11 root      rt   0       0      0      0 S   0.0  0.0   0:00.08 watchdog/1                                          
       12 root      rt   0       0      0      0 S   0.0  0.0   0:00.02 migration/1                                         
       13 root      20   0       0      0      0 S   0.0  0.0   0:00.10 ksoftirqd/1                                         
       15 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/1:0H                                        
       16 root      rt   0       0      0      0 S   0.0  0.0   0:00.08 watchdog/2                                          
       17 root      rt   0       0      0      0 S   0.0  0.0   0:00.01 migration/2                                         
       18 root      20   0       0      0      0 S   0.0  0.0   0:00.16 ksoftirqd/2                                         
       20 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/2:0H                                        
       21 root      rt   0       0      0      0 S   0.0  0.0   0:00.08 watchdog/3                                          
       22 root      rt   0       0      0      0 S   0.0  0.0   0:00.01 migration/3                                         
       23 root      20   0       0      0      0 S   0.0  0.0   0:00.14 ksoftirqd/3                                         
       25 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/3:0H                                        
       27 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 khelper                                             
       28 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kdevtmpfs                                           
       29 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 netns                                               
       30 root      20   0       0      0      0 S   0.0  0.0   0:00.01 khungtaskd                                          
       31 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 writeback                                           
       32 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kintegrityd                                         
       33 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 bioset                                              
       34 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kblockd                                             
      
    [root@localhost ~]# jps -lv
    13176 ThreadDumpTest
    13230 sun.tools.jps.Jps -Dapplication.home=/usr/local/jdk1.8.0_121 -Xms8m
    

    上面可以看到CPU使用率比较高的进程为13176, 可以定位CPU使用率过高的进程主类为ThreadDumpTest

    查看进程内使用率比较高的线程
    [root@localhost ~]# top Hp 13176
    
    top - 21:11:05 up  5:02,  3 users,  load average: 0.92, 0.49, 0.23
    Threads:  19 total,   2 running,  17 sleeping,   0 stopped,   0 zombie
    %Cpu(s): 10.6 us, 26.7 sy,  0.0 ni, 62.6 id,  0.0 wa,  0.0 hi,  0.1 si,  0.0 st
    KiB Mem :  7874196 total,  6228368 free,   854004 used,   791824 buff/cache
    KiB Swap:  8126460 total,  8126460 free,        0 used.  6713884 avail Mem 
    
      PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                              
    13193 root      20   0 4710340  61008  11976 R 34.7  0.8   0:16.40 java                                                 
    13191 root      20   0 4710340  61008  11976 R 27.3  0.8   0:20.71 java                                                 
    13192 root      20   0 4710340  61008  11976 S 14.0  0.8   0:19.79 java                                                 
    13176 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.00 java                                                 
    13177 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.04 java                                                 
    13178 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.01 java                                                 
    13179 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.02 java                                                 
    13180 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.02 java                                                 
    13181 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.02 java                                                 
    13182 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.01 java                                                 
    13183 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.00 java                                                 
    13184 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.00 java                                                 
    13185 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.00 java                                                 
    13186 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.13 java                                                 
    13187 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.10 java                                                 
    13188 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.02 java                                                 
    13189 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.00 java                                                 
    13190 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.03 java                                                 
    13290 root      20   0 4710340  61008  11976 S  0.0  0.8   0:00.00 java
    

    图中可以看到进程13176中线程13197使用CPU率最高(13191、13192其次)

    将线程号(十进制)转换后的16进制
    [root@localhost ~]# printf "%x
    " 13193
    3389
    [root@localhost ~]# printf "%x
    " 13191
    3387
    [root@localhost ~]# printf "%x
    " 13192
    3388
    
    输出线程堆栈信息
    [root@localhost ~]# jstack -l 13176
    2017-10-15 21:11:23
    Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode):
    
    "Attach Listener" #13 daemon prio=9 os_prio=0 tid=0x00007f94ac001000 nid=0x33ea waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
       Locked ownable synchronizers:
        - None
    
    "DestroyJavaVM" #12 prio=5 os_prio=0 tid=0x00007f94ec008800 nid=0x3379 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
       Locked ownable synchronizers:
        - None
    
    "测试线程2" #11 prio=5 os_prio=0 tid=0x00007f94ec0f8800 nid=0x3389 waiting for monitor entry [0x00007f94cf3f2000]
       java.lang.Thread.State: BLOCKED (on object monitor)
        at java.io.PrintStream.println(PrintStream.java:805)
        - waiting to lock <0x0000000087c06a90> (a java.io.PrintStream)
        at ThreadDumpTest$ThreadPrint.run(ThreadDumpTest.java:28)
        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)
    
       Locked ownable synchronizers:
        - <0x0000000087c06c30> (a java.util.concurrent.ThreadPoolExecutor$Worker)
    
    "测试线程1" #10 prio=5 os_prio=0 tid=0x00007f94ec0f7000 nid=0x3388 waiting for monitor entry [0x00007f94cf4f3000]
       java.lang.Thread.State: BLOCKED (on object monitor)
        at java.io.PrintStream.println(PrintStream.java:805)
        - waiting to lock <0x0000000087c06a90> (a java.io.PrintStream)
        at ThreadDumpTest$ThreadPrint.run(ThreadDumpTest.java:28)
        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)
    
       Locked ownable synchronizers:
        - <0x0000000087c06f98> (a java.util.concurrent.ThreadPoolExecutor$Worker)
    
    "测试线程0" #9 prio=5 os_prio=0 tid=0x00007f94ec0f5000 nid=0x3387 runnable [0x00007f94cf5f4000]
       java.lang.Thread.State: RUNNABLE
        at java.io.FileOutputStream.writeBytes(Native Method)
        at java.io.FileOutputStream.write(FileOutputStream.java:326)
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
        - locked <0x0000000087c21ca0> (a java.io.BufferedOutputStream)
        at java.io.PrintStream.write(PrintStream.java:482)
        - locked <0x0000000087c06a90> (a java.io.PrintStream)
        at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
        at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
        at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
        - locked <0x0000000087c081a0> (a java.io.OutputStreamWriter)
        at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
        at java.io.PrintStream.newLine(PrintStream.java:546)
        - eliminated <0x0000000087c06a90> (a java.io.PrintStream)
        at java.io.PrintStream.println(PrintStream.java:807)
        - locked <0x0000000087c06a90> (a java.io.PrintStream)
        at ThreadDumpTest$ThreadPrint.run(ThreadDumpTest.java:28)
        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)
    
       Locked ownable synchronizers:
        - <0x0000000087c0e1c0> (a java.util.concurrent.ThreadPoolExecutor$Worker)
    
    "Service Thread" #8 daemon prio=9 os_prio=0 tid=0x00007f94ec0d9800 nid=0x3385 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
       Locked ownable synchronizers:
        - None
    
    "C1 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007f94ec0bc000 nid=0x3384 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
       Locked ownable synchronizers:
        - None
    
    "C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007f94ec0ba800 nid=0x3383 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
       Locked ownable synchronizers:
        - None
    
    "C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007f94ec0b7800 nid=0x3382 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
       Locked ownable synchronizers:
        - None
    
    "Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f94ec0b6000 nid=0x3381 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
       Locked ownable synchronizers:
        - None
    
    "Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f94ec083000 nid=0x3380 in Object.wait() [0x00007f94cfcfb000]
       java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x0000000087c0e4e8> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
        - locked <0x0000000087c0e4e8> (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)
    
       Locked ownable synchronizers:
        - None
    
    "Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f94ec07e800 nid=0x337f in Object.wait() [0x00007f94cfdfc000]
       java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x0000000087c10768> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x0000000087c10768> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
    
       Locked ownable synchronizers:
        - None
    
    "VM Thread" os_prio=0 tid=0x00007f94ec076800 nid=0x337e runnable 
    
    "GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f94ec01d800 nid=0x337a runnable 
    
    "GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f94ec01f800 nid=0x337b runnable 
    
    "GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f94ec021000 nid=0x337c runnable 
    
    "GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f94ec023000 nid=0x337d runnable 
    
    "VM Periodic Task Thread" os_prio=0 tid=0x00007f94ec0dc800 nid=0x3386 waiting on condition 
    
    JNI global references: 11
    

    上面步骤中进程内高CPU线程对应的16进制分表为0x33890x33970x3388,
    分析线程快照可以看到分别对应快照中的nid=0x3389nid=0x3397nid=0x3388线程,
    发现问题代码ThreadDumpTest$ThreadPrint.run(ThreadDumpTest.java:28)

    定位问题代码

    上面高CPU线程指向的问题代码如下:

    "测试线程2" #11 prio=5 os_prio=0 tid=0x00007f94ec0f8800 nid=0x3389 waiting for monitor entry [0x00007f94cf3f2000]
       java.lang.Thread.State: BLOCKED (on object monitor)
        at java.io.PrintStream.println(PrintStream.java:805)
        - waiting to lock <0x0000000087c06a90> (a java.io.PrintStream)
        at ThreadDumpTest$ThreadPrint.run(ThreadDumpTest.java:28)
        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)
    
       Locked ownable synchronizers:
        - <0x0000000087c06c30> (a java.util.concurrent.ThreadPoolExecutor$Worker)
    

    查看我们的问题示例代码

    [root@localhost ~]# cat ThreadDumpTest.java -n
         1  import java.util.concurrent.ExecutorService;
         2  import java.util.concurrent.Executors;
         3  
         4  public class ThreadDumpTest {
         5  
         6      public static void main(String[] args) {
         7  
         8          ExecutorService executor = Executors.newFixedThreadPool(3);
         9          for(int i=0; i<5; i++){
        10              executor.submit(new ThreadPrint("测试线程"+ i));
        11          }
        12      }
        13  
        14      static class ThreadPrint implements Runnable{
        15  
        16          private String name;
        17  
        18          private ThreadPrint(String name){
        19              this.name = name;
        20          }
        21  
        22          @Override
        23          public void run() {
        24              Thread thread = Thread.currentThread();
        25              thread.setName(name);
        26              int i=0;
        27              while (true){
        28                  System.out.println(thread.getName() + "输出" + i++);
        29              }
        30          }
        31      }
        32  
        33  }
    [root@localhost ~]# 
    

    死循环输出导致CPU使用率过高.

    说明

    虚拟机执行Full GC时,会阻塞所有的用户线程。因此,即时获取到同步锁的线程也有可能被阻塞。 在查看线程Dump时,首先查看内存使用情况。

    线程状态

    通过jstack命令查看线程堆栈信息时可能会看到的线程的几种状态

    • NEW : 未启动的。不会出现在Dump中。
    • RUNNABLE : 在虚拟机内执行的。
    • BLOCKED : 受阻塞并等待监视器锁。
    • WATING : 无限期等待另一个线程执行特定操作。
    • TIMED_WATING : 有时限的等待另一个线程的特定操作。
    • TERMINATED : 已退出的。

    命令行工具-Jmap

    jmap(Java Memory Map) 用户生成堆转储快照(HeapDump), jmap的作用不仅仅是为了获取HeapDump文件, 它还可以查询finalize执行队列、Java堆和永久待的详细信息, 如空间使用率、当前用的是哪种收集器等.

    说明
    HeapDump是反应Java堆使用情况的内存镜像;其中主要包括系统信息、虚拟机属性、完整的线程Dump、所有类和对象的状态等.

    jmap语法

    [root@localhost ~]# jmap -help
    Usage:
        jmap [option] <pid>
            (to connect to running process)
        jmap [option] <executable <core>
            (to connect to a core file)
        jmap [option] [server_id@]<remote server IP or hostname>
            (to connect to remote debug server)
    
    where <option> is one of:
        <none>               to print same info as Solaris pmap
        -heap                to print java heap summary
        -histo[:live]        to print histogram of java object heap; if the "live"
                             suboption is specified, only count live objects
        -clstats             to print class loader statistics
        -finalizerinfo       to print information on objects awaiting finalization
        -dump:<dump-options> to dump java heap in hprof binary format
                             dump-options:
                               live         dump only live objects; if not specified,
                                            all objects in the heap are dumped.
                               format=b     binary format
                               file=<file>  dump heap to <file>
                             Example: jmap -dump:live,format=b,file=heap.bin <pid>
        -F                   force. Use with -dump:<dump-options> <pid> or -histo
                             to force a heap dump or histogram when <pid> does not
                             respond. The "live" suboption is not supported
                             in this mode.
        -h | -help           to print this help message
        -J<flag>             to pass <flag> directly to the runtime system
    

    参数说明

    • -heap : 显示Java堆详细信息,如使用哪种回收机,参数配置,分代状况等.只在Linux/Solaris平台下有效
    • -histo : 显示堆中对象统计信息, 包括类、示例梳理、合计容量
    • -finalizerinfo : 打印等待终结的对象信息
    • -dump : 以hprof二进制格式转储Java堆到指定filename的文件中,live子选项是可选的, 如果指定了live子选项,堆中只有活动的对象会被转储.想要浏览heap dump,你可以使用jhat(Java堆分析工具)读取生成的文件.
    • -F : 强制模式.如果指定的pid没有响应,请使用jmap -dump或jmap -histo选项.
    • -J<flag> : 指定传递给运行jmap的JVM的参数.

    jmap示例

    -heap
    [root@localhost ~]# jmap -heap 15051
    Attaching to process ID 15051, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.121-b13
    
    using thread-local object allocation.
    Parallel GC with 4 thread(s)
    
    Heap Configuration:
       MinHeapFreeRatio         = 0
       MaxHeapFreeRatio         = 100
       MaxHeapSize              = 2017460224 (1924.0MB)
       NewSize                  = 42467328 (40.5MB)
       MaxNewSize               = 672137216 (641.0MB)
       OldSize                  = 85458944 (81.5MB)
       NewRatio                 = 2
       SurvivorRatio            = 8
       MetaspaceSize            = 21807104 (20.796875MB)
       CompressedClassSpaceSize = 1073741824 (1024.0MB)
       MaxMetaspaceSize         = 17592186044415 MB
       G1HeapRegionSize         = 0 (0.0MB)
    
    Heap Usage:
    PS Young Generation
    Eden Space:
       capacity = 546832384 (521.5MB)
       used     = 111311816 (106.15522003173828MB)
       free     = 435520568 (415.3447799682617MB)
       20.355746890074453% used
    From Space:
       capacity = 59768832 (57.0MB)
       used     = 40423064 (38.550437927246094MB)
       free     = 19345768 (18.449562072753906MB)
       67.63234724078262% used
    To Space:
       capacity = 62390272 (59.5MB)
       used     = 0 (0.0MB)
       free     = 62390272 (59.5MB)
       0.0% used
    PS Old Generation
       capacity = 170393600 (162.5MB)
       used     = 68197144 (65.0378646850586MB)
       free     = 102196456 (97.4621353149414MB)
       40.02330134465144% used
    
    31756 interned Strings occupying 3488392 bytes.
    

    参数说明

    • Parallel GC with 4 thread(s): 说明使用的GC为Parallel GC

    • Heap Configuration: 堆内存初始化配置

      • MinHeapFreeRatio: 对应jvm启动参数-XX:MinHeapFreeRatio设置JVM堆最小空闲比率(default 40)
      • MaxHeapFreeRatio: 对应jvm启动参数 -XX:MaxHeapFreeRatio设置JVM堆最大空闲比率(default 70)
      • MaxHeapSize: 对应jvm启动参数-XX:MaxHeapSize=设置JVM堆的最大大小
      • NewSize: 对应jvm启动参数-XX:NewSize=设置JVM堆的‘新生代’的默认大小
      • MaxNewSize: 对应jvm启动参数-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小
      • OldSize: 对应jvm启动参数-XX:OldSize=<value>:设置JVM堆的‘老生代’的大小
      • NewRatio: 对应jvm启动参数-XX:NewRatio=:‘新生代’和‘老生代’的大小比率
      • SurvivorRatio: 对应jvm启动参数-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值
      • PermSize: 对应jvm启动参数-XX:PermSize=<value>:设置JVM堆的‘永生代’的初始大小
      • MaxPermSize: 对应jvm启动参数-XX:MaxPermSize=<value>:设置JVM堆的‘永生代’的最大大小
    • Heap Usage: 堆内存使用情况

      • PS Young Generation: 当前的年轻代内存分布
        • Eden Space: Eden区内存分布
          • capacity: 区总容量
          • used: 区已使用
          • free: 区剩余容量
        • From Space: 其中一个Survivor区的内存分布
        • To Space: 另一个Survivor区的内存分布
      • PS Old Generation: 当前的老年代内存分布
      • PS Perm Generation: 当前的 “永生代” 内存分布
    -histo

    jmap -histo 输出堆中对象统计信息(示例截取部分输出)

    [root@localhost ~]# jmap -histo 15051
    
     num     #instances         #bytes  class name
    ----------------------------------------------
       1:        500577      126716152  [C
       2:         26232       65237120  [B
       3:         14504       35776824  [I
       4:        383664        9207936  java.lang.String
       5:         64455        5672040  java.lang.reflect.Method
       6:         51405        4934880  java.util.jar.JarFile$JarFileEntry
       7:         97535        3287848  [Ljava.lang.Object;
       8:         98414        3149248  java.util.HashMap$Node
       9:         72032        2305024  java.util.concurrent.ConcurrentHashMap$Node
      10:         25440        1831680  java.lang.reflect.Field
      11:         14102        1742584  [Ljava.util.HashMap$Node;
      12:         68096        1489240  [Ljava.lang.Class;
      13:         25091        1216184  [Ljava.lang.String;
      14:         10460        1183000  java.lang.Class
      15:         24437        1172976  org.aspectj.weaver.reflect.ShadowMatchImpl
      16:          2040        1094240  [Ljava.util.concurrent.ConcurrentHashMap$Node;
      17:         31998        1023936  org.apache.ibatis.reflection.property.PropertyTokenizer
      18:         17825         998200  java.util.LinkedHashMap
      19:         13505         864320  java.net.URL
      20:         19868         794720  java.util.LinkedHashMap$Entry
      21:         24437         781984  org.aspectj.weaver.patterns.ExposedState
      22:         22626         724032  java.lang.ref.WeakReference
      23:         14512         696576  java.nio.HeapByteBuffer
      24:         14483         695184  java.nio.HeapCharBuffer
      25:         21682         693824  java.util.Hashtable$Entry
      26:         27121         650904  java.util.ArrayList
      27:         26287         630888  java.lang.StringBuilder
      28:         13050         626400  java.util.HashMap
      29:         11340         453600  com.google.common.collect.AbstractMapBasedMultimap$WrappedSet
      30:         11340         453600  com.google.common.collect.LinkedHashMultimap$ValueSet
      31:          8848         424704  org.apache.catalina.loader.ResourceEntry
      32:         10057         402280  java.util.TreeMap$Entry
      33:         17013         400008  [Ljava.lang.reflect.Type;
      34:          4850         388000  java.lang.reflect.Constructor
      35:         11918         381376  java.lang.StackTraceElement
      36:          1219         344448  [Ljava.util.Hashtable$Entry;
      37:          3921         332080  [Ljava.lang.reflect.Method;
      38:          8123         324920  java.lang.ref.Finalizer
      39:          8047         321880  java.lang.ref.SoftReference
    

    说明
    jmap -histo:live 这个命令执行,JVM会先触发gc,然后再统计信息.

    jmap -dump:format=b,file=heapDump 进程

    这个命令执行,JVM会将整个heap的信息dump写入到一个文件,heap如果比较大的话,就会导致这个过程比较耗时,并且执行的过程中为了保证dump的信息是可靠的,所以会暂停应用.

    [root@localhost ~]# jmap -dump:format=b,file=heapDump 15051
    Dumping heap to /root/heapDump ...
    Heap dump file created
    [root@localhost ~]# jhat -port 8899 heapDump
    Reading from heapDump...
    Dump file created Sun Oct 15 23:10:28 CST 2017
    Snapshot read, resolving...
    Resolving 2737044 objects...
    Chasing references, expect 547 dots...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
    Eliminating duplicate references...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
    Snapshot resolved.
    Started HTTP server on port 8899
    Server is ready.
    

    浏览器访问: http://ip:8899/

    jmap使用总结

    • 如果程序内存不足或者频繁GC,很有可能存在内存泄露情况,这时候就要借助Java堆Dump查看对象的情况
    • 要制作堆Dump可以直接使用jvm自带的jmap命令
    • 使用jmap -histo:[live]查看堆内存中的对象的情况.如果有大量对象在持续被引用,并没有被释放掉,那就产生了内存泄露,就要结合代码,把不用的对象释放掉
    • 用 jmap -dump:format=b,file=<fileName>命令将堆信息保存到一个文件中,再借助jhat命令查看详细内容
    • 在内存出现泄露、溢出或者其它前提条件下,建议多dump几次内存,把内存文件进行编号归档,便于后续内存整理分析.

    命令行工具-jhat

    jhat(JVM Heap Analysis Tool) 命令与jmap搭配使用, 用来分析jmap生成的堆转储快照, jhat内置了一个微型的HTTP/HTML服务器, 方便在浏览器中查看jmap生成的HeadpDump文件.

    jhat语法

    [root@localhost ~]# jhat -help
    Usage:  jhat [-stack <bool>] [-refs <bool>] [-port <port>] [-baseline <file>] [-debug <int>] [-version] [-h|-help] <file>
    
        -J<flag>          Pass <flag> directly to the runtime system. For
                  example, -J-mx512m to use a maximum heap size of 512MB
        -stack false:     Turn off tracking object allocation call stack.
        -refs false:      Turn off tracking of references to objects
        -port <port>:     Set the port for the HTTP server.  Defaults to 7000
        -exclude <file>:  Specify a file that lists data members that should
                  be excluded from the reachableFrom query.
        -baseline <file>: Specify a baseline object dump.  Objects in
                  both heap dumps with the same ID and same class will
                  be marked as not being "new".
        -debug <int>:     Set debug level.
                    0:  No debug output
                    1:  Debug hprof file parsing
                    2:  Debug hprof file parsing, no server
        -version          Report version number
        -h|-help          Print this help and exit
        <file>            The file to read
    
    For a dump file that contains multiple heap dumps,
    you may specify which dump in the file
    by appending "#<number>" to the file name, i.e. "foo.hprof#3".
    
    All boolean options default to "true"
    

    参数说明

    • -stack : 关闭对象分配调用栈跟踪,如果分配位置信息在堆转储中不可用,则必须将此标志设置为false. 默认值为true.
    • -refs : 关闭对象引用跟踪;默认值为true;默认情况下,返回的指针是指向其他特定对象的对象,如反向链接或输入引用,会统计/计算堆中的所有对象.
    • -port : 设置jhat HTTP server 的端口号. 默认值7000.
    • -exclude : 指定对象查询时需要排除的数据成员列表文件;例如:如果文件列列出了 java.lang.String.value,那么当从某个特定对象Object o计算可达的对象列表时,引用路径涉及 java.lang.String.value的都会被排除.
    • -baseline : 指定一个基准堆转储;在两个heap dumps中有相同object ID的对象会被标记为不是新的,其他对象被标记为新的(new),在比较两个不同的堆转储时很有用.
    • -debug : 设置debug 级别. 0表示不输出调试信息.
    • -version :启动后只显示版本信息就退出

    jhat示例

    生成java堆转储文件,并用jhat分析
    [root@localhost ~]# jmap -dump:format=b,file=heapDump 15051
    Dumping heap to /root/heapDump ...
    Heap dump file created
    [root@localhost ~]# jhat -port 8899 heapDump
    Reading from heapDump...
    Dump file created Sun Oct 15 23:10:28 CST 2017
    Snapshot read, resolving...
    Resolving 2737044 objects...
    Chasing references, expect 547 dots...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
    Eliminating duplicate references...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
    Snapshot resolved.
    Started HTTP server on port 8899
    Server is ready.
    

    示例机器ip地址: 192.168.0.107, 所以只需要访问http://192.168.0.107:8899即可, 一般查看堆异常情况主要看这个两各部分

    • 平台外的所有对象信息: Show instance counts for all classes (excluding platform)
    • 以树状图形式展示堆情况: Show heap histogram

    具体排查时需要结合代码,观察是否大量应该被回收的对象在一直被引用或者是否有占用内存特别大的对象无法被回收.

    jhat对象查询

    OQL语句的执行页面: http://ip:端口/oql/
    OQL帮助信息页面为: http://ip:端口/oqlhelp/

    参考文档


    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处

  • 相关阅读:
    Nginx(一)——介绍及安装配置
    Keepalived(二)
    H3C 交换机限速和添加Vlan
    The difference between su and su-
    CentOS7 修改 ssh 文件总结
    华为eNSP模拟器学习(一)
    如何使用Open Live Writer
    Ubuntu 开启远程ssh服务
    CentOS7 禁用firewall防火墙 启用iptables 步骤
    CentOS 7 精简版安装后联网问题
  • 原文地址:https://www.cnblogs.com/dennisit/p/9119535.html
Copyright © 2011-2022 走看看