jvm笔记3--性能监控与故障处理工具

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

1.jdk命令行工具

lib/tool.jar包
1.jps:虚拟机进程状况工具
jps [options] [hostid]
JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程。(类似UNIX的  ps命令),查看进程快照。
列出正在运行的虚拟机进程,并显示虚拟机执行主类(Main Class,main()函数所在的类)名称以及这些进程的本地虚拟机唯一ID(Local Virtual Machine Identifier,LVMID),对于本地虚拟机进程来说,LVMID与操作系统的进程ID(Process Identifier,PID)是一致的。

-q :只输出LVMID
-l  :输出主类的全名,如果进程执行的是Jar包,输出Jar路径
-v  :输出虚拟机进程启动时JVM参数
-m:输出虚拟机进程启动时,传递给主类main()函数的参数
2.jstat:虚拟机统计信息监视工具
JVM Statistics Monitoring Tool,用于监视虚拟机各种运行状态信息。显示本地或远程虚拟机进程中的类装载,内存,垃圾回收,JIT编译等运行数据。
jstat [ option vmid [ interval[s|ms] [count] ] ]
如果是本地虚拟机进程,VMID与LVMID一致,interval表示查询间隔,count表示查询次数。如:
jstat -gc 2764 250 20   表示查询2764进程 的垃圾回收情况,没250毫秒查询一次,共查询20次。

option代表查询的虚拟机信息:类装载,垃圾回收,运行期编译状态。



(S0,S1表示Survivor0,Survivor1),E表示Eden区使用55%,O表示Old老年代使用60%,P(Permanent)永久代使用99.74%。
YGC(Young GC)及Minor GC 52次,耗时0.275s。FGC(Full GC) 4次,总耗时0.458秒。GCT(GC Time)0.733秒。
3.jinfo:java配置信息工具
jinfo(Configuration Info for Java),实时查看和调整虚拟机各项参数。
jinfo -flag [+|-] name 或jinfo -flag name = vlaue来修改部分运行期参数。

4.jmap:java内存映像工具
Memory Map For Java,生成堆存储快照。不仅可以获取dump文件,还可以查询finalize执行队列,Java堆和永久代的详细信息,如空间使用率,当前使用的哪种收集器。
jmap [ option ]  vmid

输出dump快照文件。

5.jhat:虚拟机堆转储快照分析工具
JVM Heap Analysis Tool,分析jmap生成的堆转储快照。jhat内置以一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,可以在浏览器中查看。

访问:localhost:7000/
6.jstack:java堆栈跟踪工具
Stack Trace For Java,生成虚拟机当前时刻的线程快照,即当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如死锁,死循环,请求外部资源导致的长时间等待等。
在线程停顿时,通过jstack来查看各个线程的调用堆栈,就可知道没有响应的线程在后台做什么事情,或等待什么资源。
jstack [ option ] vmid
-F : 正常输出的请求不被响应时,强制输出线程堆栈
-l   :除堆栈外,显示关于锁的附加信息
-m:如果调用到本地方法的话,显示C/C++的堆栈

java.lang.Thread类有一个getAllStackTraces()方法,可获取虚拟机中所有线程的StackTraceElement对象。
可通过在服务器上添加一个jsp页面来通过浏览器查看虚拟机线程状态
<%@ page import="java.util.Map" pageEncoding="utf-8"%>
<html>
	<head>
		<title>服务器线程信息</title>
	</head>
	<body>
		<pre>
			<%
				for(Map.Entry<Thread,StackTraceElement[]> stackTrace:Thread.getAllStackTraces().entrySet()){
					Thread  thread = (Thread)stackTrace.getKey();
					StackTraceElement[] stack = (StackTraceElement[])stackTrace.getValue();
					if(thread.equals(Thread.currentThread())){
						continue;
					}
					out.print("\n线程:"+thread.getName()+"\n");
					for(StackTraceElement element:stack){
						out.print("\t"+element+"\n");
					}
				}
			%>
		</pre>
	</body>
</html>

2.jdk可视化工具

1.jconsole:java监视与管理控制台
Java Monitoring and Management Console是一种基于JMX的可视化监视,管理工具。
1.启动JConsole

jconsole.exe

2.内存监控

相当于jstat命令。监视虚拟机内存(堆和永久带)的变化趋势。

测试代码:

/**
 * VM args:-Xms100m -Xmx100m -XX:+UseSerialGC
 * 
 * @author lss
 *
 */
public class JConsoleTest {
	static class OOMObject {
		public byte[] placeholder = new byte[64 * 1024];
	}

	public static void fillHeap(int num) throws InterruptedException {
		List<OOMObject> list = new ArrayList<JConsoleTest.OOMObject>();
		for (int i = 0; i < num; i++) {
			Thread.sleep(50);
			// 每50毫秒向内存中添加64KB的数据
			list.add(new OOMObject());
		}
		System.gc();//新生代Eden和survivor区全部回收(对象转移到老年代),由于对象都被list引用,老年代中对象不回收
	}

	public static void main(String[] args) throws Exception {
		fillHeap(1000);
		
		System.out.println("hehe");
	}
}

新生代:(27/8)*10 = 34MB

老年代:66MB

对上面代码进行断点调试可以看出:新生代Eden区大小为27MB,由此可算出 整个新生代内存大小为:(27/8)*10 = 34MB

执行System.gc()后,由于对象都被list引用,所以新生代清空,对象都进入老年代,老年代内存没有回收。

3.线程监控

相当于jstack命令。

测试代码:

	/**
	 * 线程死循环
	 */
	public static void createBusyThread() {
		Thread thread = new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				while (true)
					;
			}
		}, "testBusyThread");
		thread.start();
	}

	/**
	 * 线程死锁
	 * 
	 * @param lock
	 */
	public static void createLockThread(final Object lock) {
		Thread thread = new Thread(new Runnable() {
			@Override
			public void run() {
				synchronized (lock) {
					try {
						lock.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}, "testLockThread");
		thread.start();
	}

	public static void main(String[] args) throws Exception {
		// fillHeap(1000);
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		// 控制台第一次输入,创建一个死循环的线程
		br.readLine();
		createBusyThread();
		// 控制台第二次输入,创建一个死锁的线程
		br.readLine();
		Object obj = new Object();
		createLockThread(obj);
	}

main函数中,readBytes方法被执行,但是没有检测到输入时,会立刻归还执行令牌,CPU资源消耗小

当输入内容,调用testBusyThread线程时,这个线程执行会停留在while循环处,由于死循环,线程一直占用着CPU资源,不会归还线程执行令牌。会消耗较多的CPU资源。

当再次输入,执行testLockThread线程时,线程在等待lock对象的notify,等待时处于WAITIING状态,线程只有被唤醒才会被分配执行时间。


死锁样例:

public class SynAddRunable implements Runnable {
	int a, b;

	public SynAddRunable(int a, int b) {
		this.a = a;
		this.b = b;
	}

	@Override
	public void run() {
		synchronized (Integer.valueOf(a)) {
			synchronized (Integer.valueOf(b)) {
				System.out.println(a + b);
			}
		}
	}

	public static void main(String[] args) {
		for (int i = 0; i < 100; i++) {
			new Thread(new SynAddRunable(1, 2));
			new Thread(new SynAddRunable(2, 1));
		}
	}
}
Integer.valueOf()使用了响元设计模式,对于[-128,127]之间的数会进行缓存,当调用valueOf()方法时,如果在范围内,就会直接返回缓存中的对象。上面代码调用了200次Integer.valueOf()方法,但一共就返回了两个不同的对象。

2.visualvm:多合一故障处理工具
All-in-One Java Troubleshooting Tool,对应用程序的实际性能的影响很小,使得它可以直接应用在生产环境中。基于NetBeans平台开发,具备插件扩展功能的特性。
1.VisualVM 兼容范围与插件安装
  • 显示虚拟机进程以及进程的配置,环境信息(jps,jinfo)。
  • 监视应用程序的CPU,GC,堆,方法区以及线程的信息(jstat,jstack)。
  • 方法级的程序运行性能分析,找出被调用最多,运行时间最长的方法。
  • 离线程序快照:收集程序的运行时配置,线程dump,内存dump等信息建立一个快照
插件中心地址:http://visualvm.java.net/pluginscenters.html
2.性能分析
Profiler页签,选择"CPU"和"内存"按钮中的一个进行监控。
CPU分析:统计每个方法的执行次数,执行耗时
内存分析:统计每个方法关联的对象数以及这些对象所占的空间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值