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

来源:互联网 发布:阿里云好还是腾讯云好 编辑:程序博客网 时间:2024/05/16 09:45

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

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() {@Overridepublic void run() {// TODO Auto-generated method stubwhile (true);}}, "testBusyThread");thread.start();}/** * 线程死锁 *  * @param lock */public static void createLockThread(final Object lock) {Thread thread = new Thread(new Runnable() {@Overridepublic 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;}@Overridepublic 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分析:统计每个方法的执行次数,执行耗时
内存分析:统计每个方法关联的对象数以及这些对象所占的空间

0 0
原创粉丝点击