JVM性能调优监控工具
来源:互联网 发布:再相见 方知浮生未歇 编辑:程序博客网 时间:2024/05/16 06:57
jstack
– 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。另外,jstack工具还可以附属到正在运行的java程序中,看到 当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。目前只有在Solaris和Linux的JDK版本里面才有。
jstack主要用来查看某个Java进程内的线程堆栈信息。语法格式如下:
jstack [option] pidjstack [option] executable corejstack [option] [server-id@]remote-hostname-or-ip
命令行参数选项说明如下:
-l long listings,会打印出额外的锁信息,在发生死锁时可以用jstack -l pid来观察锁持有情况-m mixed mode,不仅会输出Java堆栈信息,还会输出C/C++堆栈信息(比如Native方法)
jstack可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码,所以它在JVM性能调优中使用得非常多。下面我们来一个实例找出某个Java进程中最耗费CPU的Java线程并定位堆栈信息,用到的命令有ps、top、printf、jstack、grep。
第一步先找出Java进程ID,我部署在服务器上的Java应用名称为mrf-center:
root@ubuntu:/# ps -ef | grep mrf-center | grep -v greproot 21711 1 1 14:47 pts/3 00:02:10 java -jar mrf-center.jar
得到进程ID为21711,第二步找出该进程内最耗费CPU的线程,可以使用ps -Lfp pid或者ps -mp pid -o THREAD, tid, time或者top -Hp pid,我这里用第三个,输出如下:
TIME列就是各个Java线程耗费的CPU时间,CPU时间最长的是线程ID为21742的线程,用
printf "%x\n" 21742
得到21742的十六进制值为54ee,下面会用到。
OK,下一步终于轮到jstack上场了,它用来输出进程21711的堆栈信息,然后根据线程ID的十六进制值grep,如下:
root@ubuntu:/# jstack 21711 | grep 54ee"PollIntervalRetrySchedulerThread" prio=10 tid=0x00007f950043e000 nid=0x54ee in Object.wait() [0x00007f94c6eda000]
可以看到CPU消耗在PollIntervalRetrySchedulerThread这个类的Object.wait(),我找了下我的代码,定位到下面的代码:
// Idle waitgetLog().info("Thread [" + getName() + "] is idle waiting...");schedulerThreadState = PollTaskSchedulerThreadState.IdleWaiting;long now = System.currentTimeMillis();long waitTime = now + getIdleWaitTime();long timeUntilContinue = waitTime - now;synchronized(sigLock) { try { if(!halted.get()) { sigLock.wait(timeUntilContinue); } } catch (InterruptedException ignore) { }}
它是轮询任务的空闲等待代码,上面的sigLock.wait(timeUntilContinue)就对应了前面的Object.wait()。
jconsole – jconsole是基于Java Management Extensions (JMX)的实时图形化监测工具,这个工具利用了内建到JVM里面的JMX指令来提供实时的性能和资源的监控,包括了Java 程序的内存使用,Heap size, 线程的状态,类的分配状态和空间使用等等。
jinfo – jinfo可以从core文件里面知道崩溃的Java应用程序的配置信息,目前只有在Solaris和Linux的JDK版本里面才有。
观察运行中的java程序的运行环境参数:参数包括Java System属性和JVM命令行参数
实例:jinfo 2083
其中2083就是java进程id号,可以用jps得到这个id号。
结果:
Attaching to process ID 5655, please wait...Debugger attached successfully.Server compiler detected.JVM version is 24.79-b02Java System Properties:java.runtime.name = Java(TM) SE Runtime Environmentjava.vm.version = 24.79-b02sun.boot.library.path = /data/jdk1.7.0_79/jre/lib/amd64shared.loader = java.vendor.url = http://java.oracle.com/java.vm.vendor = Oracle Corporationpath.separator = :file.encoding.pkg = sun.iojava.vm.name = Java HotSpot(TM) 64-Bit Server VMjava.util.logging.config.file = /data/application/apache-tomcat-8.0.21/conf/logging.propertiestomcat.util.buf.StringCache.byte.enabled = truesun.os.patch.level = unknownsun.java.launcher = SUN_STANDARDuser.country = UStomcat.util.scan.StandardJarScanFilter.jarsToScan = log4j-core*.jar,log4j-taglib*.jaruser.dir = /data/application/apache-tomcat-8.0.21java.vm.specification.name = Java Virtual Machine Specificationjava.runtime.version = 1.7.0_79-b15java.awt.graphicsenv = sun.awt.X11GraphicsEnvironmentos.arch = amd64java.endorsed.dirs = /data/application/apache-tomcat-8.0.21/endorsedline.separator = java.io.tmpdir = /data/application/apache-tomcat-8.0.21/tempjava.vm.specification.vendor = Oracle Corporationjava.util.logging.manager = org.apache.juli.ClassLoaderLogManagerjava.naming.factory.url.pkgs = org.apache.namingos.name = Linuxsun.jnu.encoding = UTF-8java.library.path = /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/libjava.class.version = 51.0java.specification.name = Java Platform API Specificationsun.management.compiler = HotSpot 64-Bit Tiered Compilersos.version = 2.6.32-504.el6.x86_64user.home = /rootuser.timezone = Asia/Harbincatalina.useNaming = truejava.awt.printerjob = sun.print.PSPrinterJobfile.encoding = UTF-8java.specification.version = 1.7tomcat.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-spdy.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-*.jarcatalina.home = /data/application/apache-tomcat-8.0.21user.name = rootjava.class.path = /data/application/apache-tomcat-8.0.21/bin/bootstrap.jar:/data/application/apache-tomcat-8.0.21/bin/tomcat-juli.jarjava.naming.factory.initial = org.apache.naming.java.javaURLContextFactorypackage.definition = sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.naming.,org.apache.tomcat.java.vm.specification.version = 1.7sun.arch.data.model = 64sun.java.command = org.apache.catalina.startup.Bootstrap startjava.home = /data/jdk1.7.0_79/jreuser.language = enjava.specification.vendor = Oracle Corporationawt.toolkit = sun.awt.X11.XToolkitjava.vm.info = mixed modejava.version = 1.7.0_79java.ext.dirs = /data/jdk1.7.0_79/jre/lib/ext:/usr/java/packages/lib/extsun.boot.class.path = /data/jdk1.7.0_79/jre/lib/resources.jar:/data/jdk1.7.0_79/jre/lib/rt.jar:/data/jdk1.7.0_79/jre/lib/sunrsasign.jar:/data/jdk1.7.0_79/jre/lib/jsse.jar:/data/jdk1.7.0_79/jre/lib/jce.jar:/data/jdk1.7.0_79/jre/lib/charsets.jar:/data/jdk1.7.0_79/jre/lib/jfr.jar:/data/jdk1.7.0_79/jre/classesserver.loader = java.vendor = Oracle Corporationcatalina.base = /data/application/apache-tomcat-8.0.21file.separator = /java.vendor.url.bug = http://bugreport.sun.com/bugreport/common.loader = "${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"sun.io.unicode.encoding = UnicodeLittlesun.cpu.endian = littlepackage.access = sun.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.tomcat.sun.cpu.isalist = VM Flags:-Djava.util.logging.config.file=/data/application/apache-tomcat-8.0.21/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/data/application/apache-tomcat-8.0.21/endorsed -Dcatalina.base=/data/application/apache-tomcat-8.0.21 -Dcatalina.home=/data/application/apache-tomcat-8.0.21 -Djava.io.tmpdir=/data/application/apache-tomcat-8.0.21/temp
jmap – jmap 可以从core文件或进程中获得内存的具体匹配情况,包括Heap size, Perm size等等,目前只有在Solaris和Linux的JDK版本里面才有。
jmap语法格式如下:
jmap [option] pidjmap [option] executable corejmap [option] [server-id@]remote-hostname-or-ip
参数如下:
-heap :打印jvm heap的情况-histo: 打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。-histo:live : 同上,但是只答应存活对象的情况-permstat: 打印permanent generation heap情况
如果运行在64位JVM上,可能需要指定-J-d64命令选项参数。
jmap -permstat pid
打印进程的类加载器和类加载器加载的持久代对象信息,输出:类加载器名称、对象是否存活(不可靠)、对象地址、父类加载器、已加载的类大小等信息,如下图:
使用jmap -heap pid查看进程堆内存使用情况,包括使用的GC算法、堆配置参数和各代中堆内存使用情况。比如下面的例子:
root@ubuntu:/# jmap -heap 21711Attaching to process ID 21711, please wait...Debugger attached successfully.Server compiler detected.JVM version is 20.10-b01using thread-local object allocation.Parallel GC with 4 thread(s)Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 2067791872 (1972.0MB) NewSize = 1310720 (1.25MB) MaxNewSize = 17592186044415 MB OldSize = 5439488 (5.1875MB) NewRatio = 2 SurvivorRatio = 8 PermSize = 21757952 (20.75MB) MaxPermSize = 85983232 (82.0MB)Heap Usage:PS Young GenerationEden Space: capacity = 6422528 (6.125MB) used = 5445552 (5.1932830810546875MB) free = 976976 (0.9317169189453125MB) 84.78829520089286% usedFrom Space: capacity = 131072 (0.125MB) used = 98304 (0.09375MB) free = 32768 (0.03125MB) 75.0% usedTo Space: capacity = 131072 (0.125MB) used = 0 (0.0MB) free = 131072 (0.125MB) 0.0% usedPS Old Generation capacity = 35258368 (33.625MB) used = 4119544 (3.9287033081054688MB) free = 31138824 (29.69629669189453MB) 11.683876009235595% usedPS Perm Generation capacity = 52428800 (50.0MB) used = 26075168 (24.867218017578125MB) free = 26353632 (25.132781982421875MB) 49.73443603515625% used ....
使用jmap -histo[:live] pid查看堆内存中的对象数目、大小统计直方图,如果带上live则只统计活对象,如下:
root@ubuntu:/# jmap -histo:live 21711 | more num #instances #bytes class name---------------------------------------------- 1: 38445 5597736 <constMethodKlass> 2: 38445 5237288 <methodKlass> 3: 3500 3749504 <constantPoolKlass> 4: 60858 3242600 <symbolKlass> 5: 3500 2715264 <instanceKlassKlass> 6: 2796 2131424 <constantPoolCacheKlass> 7: 5543 1317400 [I 8: 13714 1010768 [C 9: 4752 1003344 [B 10: 1225 639656 <methodDataKlass> 11: 14194 454208 java.lang.String 12: 3809 396136 java.lang.Class 13: 4979 311952 [S 14: 5598 287064 [[I 15: 3028 266464 java.lang.reflect.Method 16: 280 163520 <objArrayKlassKlass> 17: 4355 139360 java.util.HashMap$Entry 18: 1869 138568 [Ljava.util.HashMap$Entry; 19: 2443 97720 java.util.LinkedHashMap$Entry 20: 2072 82880 java.lang.ref.SoftReference 21: 1807 71528 [Ljava.lang.Object; 22: 2206 70592 java.lang.ref.WeakReference 23: 934 52304 java.util.LinkedHashMap 24: 871 48776 java.beans.MethodDescriptor 25: 1442 46144 java.util.concurrent.ConcurrentHashMap$HashEntry 26: 804 38592 java.util.HashMap 27: 948 37920 java.util.concurrent.ConcurrentHashMap$Segment 28: 1621 35696 [Ljava.lang.Class; 29: 1313 34880 [Ljava.lang.String; 30: 1396 33504 java.util.LinkedList$Entry 31: 462 33264 java.lang.reflect.Field 32: 1024 32768 java.util.Hashtable$Entry 33: 948 31440 [Ljava.util.concurrent.ConcurrentHashMap$HashEntry;
class name是对象类型,说明如下:
B byteC charD doubleF floatI intJ longZ boolean[ 数组,如[I表示int[][L+类名 其他对象
还有一个很常用的情况是:用jmap把进程内存使用情况dump到文件中,再用jhat分析查看。jmap进行dump命令格式如下:
jmap -dump:format=b,file=dumpFileName pid
我一样地对上面进程ID为21711进行Dump:
root@ubuntu:/# jmap -dump:format=b,file=/tmp/dump.dat 21711 Dumping heap to /tmp/dump.dat ...Heap dump file created
dump出来的文件可以用MAT、VisualVM等工具查看,这里用jhat查看:
root@ubuntu:/# jhat -port 9998 /tmp/dump.datReading from /tmp/dump.dat...Dump file created Tue Jan 28 17:46:14 CST 2014Snapshot read, resolving...Resolving 132207 objects...Chasing references, expect 26 dots..........................Eliminating duplicate references..........................Snapshot resolved.Started HTTP server on port 9998Server is ready.
注意如果Dump文件太大,可能需要加上-J-Xmx512m这种参数指定最大堆内存,即jhat -J-Xmx512m -port 9998 /tmp/dump.dat。然后就可以在浏览器中输入主机地址:9998查看了:
jdb – jdb 用来对core文件和正在运行的Java进程进行实时地调试,里面包含了丰富的命令帮助您进行调试,它的功能和Sun studio里面所带的dbx非常相似,但 jdb是专门用来针对Java应用程序的。
jstat – jstat利用了JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控等等。
语法格式如下:
jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]
vmid是Java虚拟机ID,在Linux/Unix系统上一般就是进程ID。interval是采样时间间隔。count是采样数目。比如下面输出的是GC信息,采样时间间隔为250ms,采样数为4:
root@ubuntu:/# jstat -gc 21711 250 4 S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 192.0 192.0 64.0 0.0 6144.0 1854.9 32000.0 4111.6 55296.0 25472.7 702 0.431 3 0.218 0.649192.0 192.0 64.0 0.0 6144.0 1972.2 32000.0 4111.6 55296.0 25472.7 702 0.431 3 0.218 0.649192.0 192.0 64.0 0.0 6144.0 1972.2 32000.0 4111.6 55296.0 25472.7 702 0.431 3 0.218 0.649192.0 192.0 64.0 0.0 6144.0 2109.7 32000.0 4111.6 55296.0 25472.7 702 0.431 3 0.218 0.649
要明白上面各列的意义,先看JVM堆内存布局:
可以看出:
堆内存 = 年轻代 + 年老代 + 永久代年轻代 = Eden区 + 两个Survivor区(From和To)
现在来解释各列含义:
S0C、S1C、S0U、S1U:Survivor 0/1区容量(Capacity)和使用量(Used)EC、EU:Eden区容量和使用量OC、OU:年老代容量和使用量PC、PU:永久代容量和使用量YGC、YGT:年轻代GC次数和GC耗时FGC、FGCT:Full GC次数和Full GC耗时GCT:GC总耗时
jps – jps是用来查看JVM里面所有进程的具体状态, 包括进程ID,进程启动的路径等等。
jps主要用来输出JVM中运行的进程状态信息。语法格式如下:
jps [options] [hostid]
如果不指定hostid就默认为当前主机或服务器。
命令行参数选项说明如下:
-q 不输出类名、Jar名和传入main方法的参数-m 输出传入main方法的参数-l 输出main类或Jar的全限名-v 输出传入JVM的参数
比如下面:
root@ubuntu:/# jps -m -l2458 org.artifactory.standalone.main.Main /usr/local/artifactory-2.2.5/etc/jetty.xml29920 com.sun.tools.hat.Main -port 9998 /tmp/dump.dat3149 org.apache.catalina.startup.Bootstrap start30972 sun.tools.jps.Jps -m -l8247 org.apache.catalina.startup.Bootstrap start25687 com.sun.tools.hat.Main -port 9999 dump.dat21711 mrf-center.jar
jstatd
启动jvm监控服务。它是一个基于rmi的应用,向远程机器提供本机jvm应用程序的信息。默认端口1099。
实例:jstatd-J-Djava.security.policy=my.policy
my.policy文件需要自己建立,内如如下:
grantcodebase"file:$JAVA_HOME/lib/tools.jar"{ permissionjava.security.AllPermission; };
hprof(Heap/CPU Profiling Tool)
hprof能够展现CPU使用率,统计堆内存使用情况。
语法格式如下:
java -agentlib:hprof[=options] ToBeProfiledClassjava -Xrunprof[:options] ToBeProfiledClassjavac -J-agentlib:hprof[=options] ToBeProfiledClass
完整的命令选项如下:
Option Name and Value Description Default--------------------- ----------- -------heap=dump|sites|all heap profiling allcpu=samples|times|old CPU usage offmonitor=y|n monitor contention nformat=a|b text(txt) or binary output afile=<file> write data to file java.hprof[.txt]net=<host>:<port> send data over a socket offdepth=<size> stack trace depth 4interval=<ms> sample interval in ms 10cutoff=<value> output cutoff point 0.0001lineno=y|n line number in traces? ythread=y|n thread in traces? ndoe=y|n dump on exit? ymsa=y|n Solaris micro state accounting nforce=y|n force output to <file> yverbose=y|n print messages about dumps y
来几个官方指南上的实例。
CPU Usage Sampling Profiling(cpu=samples)的例子:
java -agentlib:hprof=cpu=samples,interval=20,depth=3 Hello
上面每隔20毫秒采样CPU消耗信息,堆栈深度为3,生成的profile文件名称是java.hprof.txt,在当前目录。
CPU Usage Times Profiling(cpu=times)的例子,它相对于CPU Usage Sampling Profile能够获得更加细粒度的CPU消耗信息,能够细到每个方法调用的开始和结束,它的实现使用了字节码注入技术(BCI):
javac -J-agentlib:hprof=cpu=times Hello.java
Heap Allocation Profiling(heap=sites)的例子:
javac -J-agentlib:hprof=heap=sites Hello.java
Heap Dump(heap=dump)的例子,它比上面的Heap Allocation Profiling能生成更详细的Heap Dump信息:
javac -J-agentlib:hprof=heap=dump Hello.java
虽然在JVM启动参数中加入-Xrunprof:heap=sites参数可以生成CPU/Heap Profile文件,但对JVM性能影响非常大,不建议在线上服务器环境使用。
- JVM性能调优监控工具
- JVM性能调优监控工具
- JVM性能调优监控工具
- jvm 性能监控 调优工具
- JVM性能调优监控工具
- JVM性能调优监控工具总结
- JVM性能调优监控工具
- JVM性能调优监控工具
- JVM 性能监控工具
- JVM性能监控工具
- JVM性能调优监控工具hprof使用详解
- JVM性能调优监控工具专题一
- JVM性能调优监控工具hprof使用详解
- JVM 性能监控调优
- jvm 基础 性能监控工具
- JVM性能监控工具使用
- 深入JVM-性能监控工具
- JVM性能监控工具-Jvisualvm
- List集合
- 基于dubbo框架下的RPC通讯协议性能测试
- alexnet tensorflow 实现和训练
- 4.5 服务器上的 Git - Git 守护进程
- opencv双目视觉标定、匹配和测量 (附代码)
- JVM性能调优监控工具
- Matlab相关工具箱下载地址汇总
- String.xml Error:(2) Apostrophe not preceded by \ (in It 's said that
- gnuplot绘制圆
- Ajax详解
- java与html
- C++中对纯虚函数和多态的理解
- BITCS2016程序设计 | 4. 合并果子
- 2016云栖大会即将开幕,阿里聚安全邀您共同见证盛典