虚拟机性能监控与故障处理

提纲

JDK的命令行工具

1.进程状况查看工具

  1. jps -l输出主类的全名
  2. Jps -q省略主类的名称
  3. Jps -m输出进程启动时传递给主类main()函数的参数
  4. Jps -v输出进程启动时jvm的参数

2.虚拟机统计信息监视工具

jstat [ option vmid [interval(查询间隔)[s|ms] [count(次数)]] ]

例:

C:\Users\lenovo>jstat -class 18704 250 5(监视类装载Loaded、卸载数量Unloaded、总空间以及类装载所耗费的时间Time)
Loaded  Bytes  Unloaded  Bytes     Time
 21617 46751.3       30    46.8     144.20
 21617 46751.3       30    46.8     144.20
 21617 46751.3       30    46.8     144.20
 21617 46751.3       30    46.8     144.20
 21617 46751.3       30    46.8     144.20
C:\Users\lenovo>jstat -gc 18704 250 20(监视java堆情况,包括Eden区、两个survivor区、老年代、永久代的容量、已用空间、gc时间合计等信息。)
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       PC     PU    YGC     YGCT    FGC    FGCT     GCT  
31744.0 512.0   0.0    0.0   229376.0   83.0    349696.0   230084.0  187904.0 133283.5     45    1.144  11      7.977    9.121
C:\Users\lenovo>jstat -gccapacity 18704 250 2(输出主要关注java堆各个区域使用到的最大最小空间)
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC      PGCMN    PGCMX     PGC       PC     YGC    FGC
175104.0 349696.0 286720.0 27648.0 28672.0 229376.0   349696.0   698880.0   349696.0   349696.0  21504.0 262144.0 167936.0 167936.0     48    14
175104.0 349696.0 286720.0 27648.0 28672.0 229376.0   349696.0   698880.0   349696.0   349696.0  21504.0 262144.0 167936.0 167936.0     48    14

C:\Users\lenovo>jstat -gcutil 18704 250 2(输出主要关注已使用空间站总空间的百分比)
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT
  0.00   0.00   0.37  57.38  81.83     49    1.218    15   10.599   11.817
  0.00   0.00   0.37  57.38  81.83     49    1.218    15   10.599   11.817

C:\Users\lenovo>jstat -gccause 18704 250 2(额外输出导致上一次gc产生的原因)
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT    LGCC                 GCC
  0.00   0.00   0.51  57.38  81.83     49    1.218    15   10.599   11.817 System.gc()          No GC
  0.00   0.00   0.51  57.38  81.83     49    1.218    15   10.599   11.817 System.gc()          No GC

C:\Users\lenovo>jstat -gcnew 18704 250 2监视新生代
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT
27136.0 1024.0    0.0    0.0  1  15 27136.0 229376.0   1168.8     49    1.218
27136.0 1024.0    0.0    0.0  1  15 27136.0 229376.0   1168.8     49    1.218

C:\Users\lenovo>jstat -gcnewcapacity 18704 250 2
  NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC      YGC   FGC
  175104.0   349696.0   281600.0 116224.0  25088.0 116224.0  26112.0   348672.0   229376.0    50    16
  175104.0   349696.0   281600.0 116224.0  25088.0 116224.0  26112.0   348672.0   229376.0    50    16

C:\Users\lenovo>jstat -gcold 18704 250 2监视老年代
   PC       PU        OC          OU       YGC    FGC    FGCT     GCT
158208.0 133229.8    349696.0    200472.1     50    16   10.943   12.179
158208.0 133229.8    349696.0    200472.1     50    16   10.943   12.179

C:\Users\lenovo>jstat -gcoldcapacity 18704 250 2
   OGCMN       OGCMX        OGC         OC       YGC   FGC    FGCT     GCT
   349696.0    698880.0    349696.0    349696.0    50    16   10.943   12.179
   349696.0    698880.0    349696.0    349696.0    50    16   10.943   12.179

C:\Users\lenovo>jstat -gcpermcapacity 18704 250 2输出永久代的最大、最小使用空间
  PGCMN      PGCMX       PGC         PC      YGC   FGC    FGCT     GCT
   21504.0   262144.0   158208.0   158208.0    50    16   10.943   12.179
   21504.0   262144.0   158208.0   158208.0    50    16   10.943   12.179

C:\Users\lenovo>jstat -compiler 18704 250 2输出jit编译器编译过的方法、耗时信息
Compiled Failed Invalid   Time   FailedType FailedMethod
    3541      1       0    65.49          1 com/google/inject/spi/InjectionPoint getInjectionPoints
    3541      1       0    65.49          1 com/google/inject/spi/InjectionPoint getInjectionPoints

C:\Users\lenovo>jstat -printcompilation 18704 250 2输出已经被jit编译过的方法
Compiled  Size  Type Method
    3541     79    1 org/eclipse/swt/widgets/Display checkDevice
3541     79    1 org/eclipse/swt/widgets/Display checkDevice

3.Java配置信息工具:jinfo

Usage:

   jinfo [option] <pid>

       (连接正在运行的进程)

   jinfo [option] <executable <core>

       (连接可运行的核心文件)

   jinfo [option] [server_id@]<remote server IP or hostname>

       (连接远程的)

 

where <option> is one of:option可以为以下信息

   -flag <name>         打印指定jvm的参数值

   -flag [+|-]<name>    设置指定jvm参数的布尔值

   -flag <name>=<value> 设置指定jvm参数的值

   -flags               打印所有jvm参数

   -sysprops            打印系统属性

   <no option>         打印所有信息

-h | -help           to print this help message

4.Java内存映像工具:jmap

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>              打印与Solaris pmap相同的信息

   -heap                打印java堆摘要

   -histo[:live]        打印Java对象统计信息;如果指定“活”子选项,则只计数活动对象

   -permstat            打印永久代生成的统计数据

   -finalizerinfo       打印关于在finaizer队列中的对象的信息

   -dump:<dump-options> 以hprof二进制格式转储java堆

                         dump-options:

                           live         仅转储活动对象;如果没有指定,堆中的所有对象都被存储。

                           format=b     binary format

                          file=<file>  dump heap to<file>

                         Example: jmap-dump:live,format=b,file=heap.bin <pid>

   -F                   强制。与-dump:<dump-options>  <pid>或-histo一起使用以在<pid>不响应时强制堆转储或直方图。 “实时”子选项不受支持

                         in this mode.

   -h | -help           to print this help message

-J<flag>             将<flag>直接传递给运行时的系统

示例--打印对象统计信息:

示例--输出堆快照

示例--打印finalizer队列中的信息

5.虚拟机堆转出快照分析工具:Jhat

Usage:  jhat [-stack <bool>] [-refs<bool>] [-port <port>] [-baseline <file>] [-debug<int>] [-version] [-h|-help] <file>

 

        -J<flag>         直接将<flag>传递给运行时系统。例如,-J-mx512m的最大堆大小为512MB

        -stack false:     关闭跟踪对象分配调用堆栈。

        -refs false:      关闭跟踪对象的引用

        -port <port>:     设置HTTP服务器的端口。默认为7000

        -exclude <file>:  指定一个文件,列出应该从查询中可访问的地方排除的数据成员。

        -baseline <file>: 指定一个基线对象转储。具有相同ID和相同类的堆转储中的对象将被标记为不是“新”。

        -debug <int>:    设置调试级别

                            0:  没有调试输出

                            1:  调试hprof文件解析

                            2:  调试hprof文件解析,不需要服务器

        -version          报告版本号

        -h|-help          Print this help and exit

        <file>            要读取的文件

示例--分析堆快照

登陆localhost:7000,使用OQL或者其他工具进行查看

6.Java对栈跟踪工具:Jstack

Usage:

    jstack [-l] <pid>

        (to connect to running process)

    jstack -F [-m] [-l] <pid>

        (连接到一个挂起的进程)

    jstack [-m] [-l] <executable><core>

        (to connect to a core file)

    jstack [-m] [-l] [server_id@]<remoteserver IP or hostname>

        (to connect to a remote debug server)

 

Options:

    -F 强制线程转储。在jstack <pid>不响应时使用(进程挂起)

    -m 打印java和本机帧(混合模式)

    -l 详细信息。打印有关锁定的其他信息

    -h or -help to print this help message

示例--jstack查看堆栈信息

package chapter6;

import java.util.concurrent.locks.ReentrantLock;

public class DeadLock extends Thread	{
	protected Object myDirect;
	static ReentrantLock south = new ReentrantLock();
	static ReentrantLock north = new ReentrantLock();
	public DeadLock(Object myDirect) {
		super();
		this.myDirect = myDirect;
		if(this.myDirect==south){
			this.setName("south");
		}
		if(this.myDirect==north){
			this.setName("north");
		}
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();
		if(myDirect==south){
			try {
				north.lockInterruptibly();
				Thread.sleep(500);
				south.lockInterruptibly();
				System.out.println("car to south has passed");
			} catch (InterruptedException e) {
				System.out.println("car to south is killed");
			}finally{
				if(north.isHeldByCurrentThread())
					north.unlock();
				if(south.isHeldByCurrentThread())
					south.unlock();
			}
		}
		if(myDirect==north){
			try {
				south.lockInterruptibly();
				Thread.sleep(500);
				north.lockInterruptibly();
				System.out.println("car to north has passed");
			} catch (InterruptedException e) {
				System.out.println("car to north is killed");
			}finally{
				if(north.isHeldByCurrentThread())
					north.unlock();
				if(south.isHeldByCurrentThread())
					south.unlock();
			}
		}
		
	}
	public static void main(String[] args) throws InterruptedException {
		DeadLock car2south = new DeadLock(south);
		DeadLock car2north = new DeadLock(north);
		car2south.start();
		car2north.start();
		Thread.sleep(1000);
	}
}

输入命令行,新查询对应的pid。

查看结果:

6.远程主机信息收集:jstatd

将本地jvm作为服务器向远程开放。直接打开时,创建失败:

新建文本文档并编辑:

重新运行:

查看开启的RMI服务器:

显示远程计算机的java进程

查看远程进程中Main的gc情况:

7.多功能命令行:jcmd

Usage: jcmd <pid | main class> <command ...|PerfCounter.print|-f file>
   or: jcmd -l
   or: jcmd -h

  命令必须是所选jvm的有效jcmd命令。
  使用命令“help”查看哪些命令可用。
  如果pid为0,则命令将被发送到所有Java进程。
  主类参数将用于匹配(部分地)
  或完全)用于启动Java的类。
  如果没有给出选项,则列出Java进程(与-p相同)。

  PerfCounter.print显示此进程公开的计数器
  -f  从文件读取并执行命令
  -l  列出本地机器上的JVM进程
  -h  this help

8.性能统计工具-hprof

hprof usage: java -agentlib:hprof=[help]|[<option>=<value>, ...]

Option Name and Value  Description                    Default
---------------------  -----------                    -------
heap=dump|sites|all    堆分析                         all
cpu=samples|times|old  CPU usage                      off
monitor=y|n            监视争用                        n
format=a|b             text(txt) or binary output     a
file=<file>            将数据写入文件                  java.hprof[{.txt}]
net=<host>:<port>      通过套接字发送数据              off
depth=<size>           堆栈跟踪深度                    4
interval=<ms>          采样间隔以毫秒为单位             10
cutoff=<value>         output cutoff point            0.0001
lineno=y|n             line number in traces?         y
thread=y|n             thread in traces?              n
doe=y|n                dump on exit?                  y
msa=y|n                Solaris micro state accounting n
force=y|n              force output to <file>         y
verbose=y|n            print messages about dumps     y

Obsolete Options
----------------
gc_okay=y|n

 示例--使用hprof统计性能信息

package chapter6;
//去掉包名运行
public class HprofTest {
	public void slowMethod(){
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public void slowerMethod(){
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public void fastMethod(){
		try{
			Thread.yield();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		HprofTest test = new HprofTest();
		test.fastMethod();
		test.slowMethod();
		test.slowerMethod();
	}
}

结果:

7.JIT生成代码反汇编:HSDIS

引用并参考:在64位Windows上编译hsdis_yizishou的博客-CSDN博客_hsdis-amd64.dylib

步骤:

1.下载安装Cygwin;

  进入select包时,安装如下包:

  • Devel - make
  • Devel - gcc-core
  • Devel - mingw64-x86_64-gcc-core
  • Utils - diffutils

2.下载beanutil与openjdk源码,并复制到如下目录

beanutil下载openjdk源码下载

openjdk下载步骤:tags——>相应版本—>bz2


  1. 将下载的binutils、openJDK源码/src/share/tools/hsdi解压到~下 
  2. 修改~/hsdis/Makefile文件,搜索LIBRARIES,将 
    LIBRARIES = $(TARGET_DIR)/bfd/libbfd.a \ 
    $(TARGET_DIR)/opcodes/libopcodes.a \ 
    $(TARGET_DIR)/libiberty/libiberty.a 
    修改为 
    LIBRARIES = $(TARGET_DIR)/bfd/libbfd.a \ 
    $(TARGET_DIR)/zlib/libz.a \ 
    $(TARGET_DIR)/opcodes/libopcodes.a \ 
    $(TARGET_DIR)/libiberty/libiberty.a 
    保存
  3. 在Cygwin窗口输入cd ~/hsdis,然后输入命令make OS=Linux MINGW=x86_64-w64-mingw32 'AR=$(MINGW)-ar' BINUTILS=~/binutils-2.27(最后的binutils路径需要与实际安装路径一致)
  4. 编译完,hsdis-amd64.dll现在就在~/hsdis/build/Linux-amd64里面了,把它复制到$JAVA_HOME/jre/bin/server(或$JAVA_HOME/jre/bin/client下面。

示例:

package hsdis;
/**
 * HSDIS:JIT生成反代码汇编
 * java -XX:+UnlockDIagnosticVMOptions -XX:+PrintAssembly 
 * -Xcomp -XX:CompileCommand=dontinline,*Bar.sum 
 * -XXCompileCommand=compileonly,*Bar.sum hsdis.Bar
 * @author shiker
 *
 */
public class Bar {


	int a=1;
	static int b=2;
	
	public int sum(int c){
		return a+b+c;
	}
	
	public static void main(String[] args) {
		new Bar().sum(3);
	}
}

编译后:

D:\Program\demo\bin>java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -Xcomp -XX:CompileCommand=dontinline,*.Bar.sum -XX:CompileCommand=compileonly,*Bar.sum demo.Bar
Java HotSpot(TM) 64-Bit Server VM warning: PrintAssembly is enabled; turning on DebugNonSafepoints to gain additional output
CompilerOracle: unrecognized line
  "dontinline * Bar sum"
  Unrecognized text after command:  sum
CompilerOracle: compileonly *Bar.sum
Loaded disassembler from D:\jdk1.7\jre\bin\server\hsdis-amd64.dll
Decoding compiled method 0x00000000032431d0:
Code:
[Disassembling for mach='i386:x86-64']
[Entry Point]
[Constants]
  # {method} 'sum' '(I)I' in 'demo/Bar'
  # this:     rdx:rdx   = 'demo/Bar'
  # parm0:    r8        = int
  #           [sp+0x20]  (sp of caller)
  0x0000000003243300: mov    0x8(%rdx),%r10d
  0x0000000003243304: shl    $0x3,%r10
  0x0000000003243308: cmp    %r10,%rax
  0x000000000324330b: jne    0x0000000003217a60  ;   {runtime_call}
  0x0000000003243311: data16 xchg %ax,%ax
  0x0000000003243314: nopl   0x0(%rax,%rax,1)
  0x000000000324331c: data16 data16 xchg %ax,%ax
[Verified Entry Point]
  0x0000000003243320: sub    $0x18,%rsp
  0x0000000003243327: mov    %rbp,0x10(%rsp)    ;*synchronization entry
                                                ; - demo.Bar::sum@-1 (line 9)
  0x000000000324332c: movabs $0x7d5d9b0a8,%r10  ;   {oop(a 'java/lang/Class' = 'demo/Bar')}
  0x0000000003243336: mov    0x58(%r10),%r10d
  0x000000000324333a: add    0xc(%rdx),%r10d
  0x000000000324333e: mov    %r8d,%eax
  0x0000000003243341: add    %r10d,%eax         ;*iadd
                                                ; - demo.Bar::sum@9 (line 9)
  0x0000000003243344: add    $0x10,%rsp
  0x0000000003243348: pop    %rbp
  0x0000000003243349: test   %eax,-0x230334f(%rip)        # 0x0000000000f40000
                                                ;   {poll_return}
  0x000000000324334f: retq
  0x0000000003243350: hlt
  0x0000000003243351: hlt
  0x0000000003243352: hlt
  0x0000000003243353: hlt
  0x0000000003243354: hlt
  0x0000000003243355: hlt
  0x0000000003243356: hlt
  0x0000000003243357: hlt
  0x0000000003243358: hlt
  0x0000000003243359: hlt
  0x000000000324335a: hlt
  0x000000000324335b: hlt
  0x000000000324335c: hlt
  0x000000000324335d: hlt
  0x000000000324335e: hlt
  0x000000000324335f: hlt
[Exception Handler]
[Stub Code]
  0x0000000003243360: jmpq   0x00000000032400a0  ;   {no_reloc}
[Deopt Handler Code]
  0x0000000003243365: callq  0x000000000324336a
  0x000000000324336a: subq   $0x5,(%rsp)
  0x000000000324336f: jmpq   0x0000000003219000  ;   {runtime_call}
  0x0000000003243374: hlt
  0x0000000003243375: hlt
  0x0000000003243376: hlt
  0x0000000003243377: hlt

JDK的可视化工具

1.Java监视与管理控制台:JConsole

启动JConsole:JDK/bin/jconsole.exe

功能:内存监控、线程监控

2.多合一故障处理工具:VisualVM

Visual插件安装

功能:生成、浏览堆转储快照

      分析程序性能

      BTrace动态日志跟踪

官方插件下载地址:VisualVM: Plugins Centers

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值