java监控工具VisualVM

https://visualvm.github.io/

https://visualvm.github.io/documentation.html

https://htmlpreview.github.io/?https://raw.githubusercontent.com/visualvm/visualvm.java.net.backup/master/www/zh_CN/gettingstarted.html

https://htmlpreview.github.io/?https://raw.githubusercontent.com/visualvm/visualvm.java.net.backup/master/www/zh_CN/intro.html

转自:http://www.cnblogs.com/wade-xu/p/4369094.html

这篇总结的很不错(本人亲自操手学习),留着以后复习备用,很适合入门级的学习者:

VisualVM 是一款免费的,集成了多个 JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优。这些功能包括生成和分析海量数据、跟踪内存泄漏、监控垃圾回收器、执行内存和 CPU 分析,同时它还支持在 MBeans 上进行浏览和操作。本文主要介绍如何使用 VisualVM 进行性能分析及调优。

准备工作

自从 JDK 6 Update 7 以后已经作为 Oracle JDK 的一部分,位于 JDK 根目录的 bin 文件夹下,无需安装,直接运行即可。

内存分析篇

VisualVM 通过检测 JVM 中加载的类和对象信息等帮助我们分析内存使用情况,我们可以通过 VisualVM 的监视标签对应用程序进行内存分析。

1)内存堆Heap

首先我们来看内存堆Heap使用情况,我本机eclipse的进程在visualVM显示如下:

随便写个小程序占用内存大的,运行一下

程序如下:

 1 package jvisualVM;
2
3 public class JavaHeapTest {
4 public final static int OUTOFMEMORY = 200000000;
5
6 private String oom;
7
8 private int length;
9
10 StringBuffer tempOOM = new StringBuffer();
11
12 public JavaHeapTest(int leng) {
13 this.length = leng;
14
15 int i = 0;
16 while (i < leng) {
17 i++;
18 try {
19 tempOOM.append("a");
20 } catch (OutOfMemoryError e) {
21 e.printStackTrace();
22 break;
23 }
24 }
25 this.oom = tempOOM.toString();
26
27 }
28
29 public String getOom() {
30 return oom;
31 }
32
33 public int getLength() {
34 return length;
35 }
36
37 public static void main(String[] args) {
38 JavaHeapTest javaHeapTest = new JavaHeapTest(OUTOFMEMORY);
39 System.out.println(javaHeapTest.getOom().length());
40 }
41
42 }

查看VisualVM Monitor tab, 堆内存变大了

在程序运行结束之前, 点击Heap Dump 按钮, 等待一会儿,得到dump结果,可以看到一些Summary信息

点击Classes, 发现char[]所占用的内存是最大的

双击它,得到如下Instances结果

Instances是按Size由大到小排列的

第一个就是最大的, 展开Field区域的 values

StringBuffer类型的 全局变量 tempOOM 占用内存特别大, 注意局部变量是无法通过 堆dump来得到分析结果的。

另外,对于“堆 dump”来说,在远程监控jvm的时候,VisualVM是没有这个功能的,只有本地监控的时候才有。

###转载注明出处:http://www.cnblogs.com/wade-xu/p/4369094.html

2)永久保留区域PermGen

其次来看下永久保留区域PermGen使用情况

运行一段类加载的程序,代码如下:

 1 package jvisualVM;
2
3 import java.io.File;
4 import java.lang.reflect.Method;
5 import java.net.MalformedURLException;
6 import java.net.URL;
7 import java.net.URLClassLoader;
8 import java.util.ArrayList;
9 import java.util.List;
10
11 public class TestPermGen {
12
13 private static List<Object> insList = new ArrayList<Object>();
14
15 public static void main(String[] args) throws Exception {
16
17 permLeak();
18 }
19
20 private static void permLeak() throws Exception {
21 for (int i = 0; i < 1000; i++) {
22 URL[] urls = getURLS();
23 URLClassLoader urlClassloader = new URLClassLoader(urls, null);
24 Class<?> logfClass = Class.forName("org.apache.commons.logging.LogFactory", true,urlClassloader);
25 Method getLog = logfClass.getMethod("getLog", String.class);
26 Object result = getLog.invoke(logfClass, "TestPermGen");
27 insList.add(result);
28 System.out.println(i + ": " + result);
29 }
30 }
31
32 private static URL[] getURLS() throws MalformedURLException {
33 File libDir = new File("C:/Users/wadexu/.m2/repository/commons-logging/commons-logging/1.1.1");
34 File[] subFiles = libDir.listFiles();
35 int count = subFiles.length;
36 URL[] urls = new URL[count];
37 for (int i = 0; i < count; i++) {
38 urls[i] = subFiles[i].toURI().toURL();
39 }
40 return urls;
41 }
42
43
44 }

一个类型装载之后会创建一个对应的java.lang.Class实例,这个实例本身和普通对象实例一样存储于堆中,我觉得之所以说是这是一种特殊的实例,某种程度上是因为其充当了访问PermGen区域中类型信息的代理者。

运行一段时间后抛OutOfMemoryError了, VisualVM监控结果如下:

结论:PermGen区域分配的堆空间过小,我们可以通过设置-XX: PermSize参数和-XX:MaxPermSize参数来解决。

关于PermGen OOM深入分析请参考这篇文章

关于Perform GC, 请参考这篇文章

###转载注明出处:http://www.cnblogs.com/wade-xu/p/4369094.html

CPU分析篇

CPU 性能分析的主要目的是统计函数的调用情况及执行时间,或者更简单的情况就是统计应用程序的 CPU 使用情况。

没有程序运行时的 CPU 使用情况如下图:

运行一段 占用CPU 的小程序,代码如下

package jvisualVM;

public class MemoryCpuTest {

    public static void main(String[] args) throws InterruptedException {

        cpuFix();
} /**
* cpu 运行固定百分比
*
* @throws InterruptedException
*/
public static void cpuFix() throws InterruptedException {
// 80%的占有率
int busyTime = 8;
// 20%的占有率
int idelTime = 2;
// 开始时间
long startTime = 0; while (true) {
// 开始时间
startTime = System.currentTimeMillis(); /*
* 运行时间
*/
while (System.currentTimeMillis() - startTime < busyTime) {
;
} // 休息时间
Thread.sleep(idelTime);
}
}
}

查看监视页面 Monitor tab

过高的 CPU 使用率可能是由于我们的项目中存在低效的代码;

在我们对程序施压的时候,过低的 CPU 使用率也有可能是程序的问题。

点击取样器Sampler, 点击“CPU”按钮, 启动CPU性能分析会话,VisualVM 会检测应用程序所有的被调用的方法,

在CPU samples tab 下可以看到我们的方法cpufix() 的自用时间最长, 如下图:

切换到Thread CPU Time 页面下,我们的 main 函数这个进程 占用CPU时间最长, 如下图:

###转载注明出处:http://www.cnblogs.com/wade-xu/p/4369094.html

线程分析篇

Java 语言能够很好的实现多线程应用程序。当我们对一个多线程应用程序进行调试或者开发后期做性能调优的时候,往往需要了解当前程序中所有线程的运行状态,是否有死锁、热锁等情况的发生,从而分析系统可能存在的问题。

在 VisualVM 的监视标签内,我们可以查看当前应用程序中所有活动线程(Live threads)和守护线程(Daemon threads)的数量等实时信息。

运行一段小程序,代码如下:

package jvisualVM;

public class MyThread extends Thread{

    public static void main(String[] args) {

        MyThread mt1 = new MyThread("Thread a");
MyThread mt2 = new MyThread("Thread b"); mt1.setName("My-Thread-1 ");
mt2.setName("My-Thread-2 "); mt1.start();
mt2.start();
} public MyThread(String name) {
} public void run() { while (true) { }
} }

Live threads 从11增加两个 变成13了

Daemon threads从8增加两个 变成10了

VisualVM 的线程标签提供了三种视图,默认会以时间线的方式展现, 如下图:

可以看到两个我们run的程序里启的线程:My-Thread-1 和 My-Thread-2

另外还有两种视图分别是表视图和详细信息视图, 这里看一下每个Thread的详细视图:

###转载注明出处:http://www.cnblogs.com/wade-xu/p/4369094.html

再来一段死锁的程序,看VisualVM 能否分析出来

package jvisualVM;

public class DeadLock {
public static void main(String[] args) {
Resource r1 = new Resource();
Resource r0 = new Resource(); Thread myTh1 = new LockThread1(r1, r0);
Thread myTh0 = new LockThread0(r1, r0); myTh1.setName("DeadLock-1 ");
myTh0.setName("DeadLock-0 "); myTh1.start();
myTh0.start();
}
} class Resource {
private int i; public int getI() {
return i;
} public void setI(int i) {
this.i = i;
} } class LockThread1 extends Thread {
private Resource r1, r2; public LockThread1(Resource r1, Resource r2) {
this.r1 = r1;
this.r2 = r2;
} @Override
public void run() {
int j = 0;
while (true) {
synchronized (r1) {
System.out.println("The first thread got r1's lock " + j);
synchronized (r2) {
System.out.println("The first thread got r2's lock " + j);
}
}
j++;
}
} } class LockThread0 extends Thread {
private Resource r1, r2; public LockThread0(Resource r1, Resource r2) {
this.r1 = r1;
this.r2 = r2;
} @Override
public void run() {
int j = 0;
while (true) {
synchronized (r2) {
System.out.println("The second thread got r2's lock " + j);
synchronized (r1) {
System.out.println("The second thread got r1's lock" + j);
}
}
j++;
}
} }

打开VisualVM检测到的JVM进程,我们可以看到这个tab在闪,VisualVM已经检测到我这个package下面的DeadLock类出错了

切换到Thread tab, 可以看到死锁了, Deadlock detected!

另外可以点击Thread Dump 线程转储,进一步分析,在这里就不赘述了,有兴趣的读者可以自行实验。

参考文献:

http://www.ibm.com/developerworks/cn/java/j-lo-visualvm/

远程监控

ps:尝试了网上的几个网友提供的方法,始终不得其法,汇总后,终于尝试成功!将一些需要注意的细节也记录下来以后备用!

我们经常需要对我们的开发的软件做各种测试, 软件对系统资源的使用情况更是不可少, 目前有多个监控工具, 相比JProfiler对系统资源尤其是内存的消耗是非常庞大,JDK1.6开始自带的VisualVM就是不错的监控工具.
这个工具就在JAVA_HOME\bin\目录下的jvisualvm.exe, 双击这个文件就能看到一个比较直观的界面.

要进行远程监控, 本机的VisualVM就必须和远程的JVM要进行通信, Visualvm目前支持两种remote connection方式.
分别是jstatd和JMX方式: 这里主要介绍的是通过JMX方式.

JMX方式:

首先讲述需要账号密码的方式:

  1.修改远程需要被监控机子的jdk配置文件;
  •   进入JAVA_HOME\jre\lib\management\
  •   拷贝一份jmxremote.password.template并改名为jmxremote.password到当前目录,并去掉# monitorRole  QED 和 # controlRole  R&D 这两行  前面的注释符号.
  •   这里是设置 远程登录的账号和密码。比如默认的 账号是 monitorRole 和controlRole,其对应的密码分别是 QED和 R&D;可以自定义用户名密码,我自  定义了一个账号密码都为 root的账号。如图:

    

  •   同时需要修改 当前目录里的jmxremote.access 文件,该文件可以控制访问权限;如图:

    

  2.修改远程机器上需要被监控的程序的配置文件 (我这里是监控Tomcat容器内部署的应用).

   修改TOMCAT_HOME/bin/catalian.sh文件;

    在第一行加入如下语句:

    export JAVA_OPTS="-Djava.rmi.server.hostname=192.168.2.120 -Dcom.sun.management.jmxremote.port=18999  -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=true"

    ps: 我需要监控的tomcat机子ip为 192.168.2.120;监控端口设置为:18999;远程认证设置(默认)为true;

      当时就因为很多资料上没有 将JAVA_OPTS变量 export,导致失败了多次。

    详细的参数见下面:    

 参数 描述
com.sun.management.jmxremote true / false. Default is true
com.sun.management.jmxremote.port Port number. No default.
com.sun.management.jmxremote.ssl true / false. Default is true.
com.sun.management.jmxremote.ssl.enabled.protocols Default SSL/TLS protocol version.
com.sun.management.jmxremote.ssl.enabled.cipher.suites Default SSL/TLS cipher suites.
com.sun.management.jmxremote.ssl.need.client.auth true / false. Default is false
com.sun.management.jmxremote.authenticate true / false.Default is true
com.sun.management.jmxremote.password.file JRE_HOME/lib/management/jmxremote.password
com.sun.management.jmxremote.access.file JRE_HOME/lib/management/jmxremote.access
com.sun.management.jmxremote.login.config Default login configuration is a file-based password authentication
  3.重启tomcat,让配置生效。

  ps: 可以用 netstat -anp| grep 18999 ,查看守护线程是否已经启动!如图:

    

  4.VisualVM配置。
  •   打开你本机命令框,输入jvisualvm,点击这个EXE文件;或者进入JAVA_HOME\bin\目录下面点击也可以!

  •   右击远程,点击添加远程主机:

    

  •   右击 192.168.2.120(远程主机),添加一个JMX链接,如图:

    

  • 登录后状态:  

  

ps:

不需要账号密码登录的,设置:-Dcom.sun.management.jmxremote.authenticate=false 即可。

export JAVA_OPTS="-Djava.rmi.server.hostname=192.168.2.120 -Dcom.sun.management.jmxremote.port=18999  -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false" 如图:

输入端口,直接点击确定,即可登录!

Jstatd方法:(略)还没有试过!

参考文件:

https://segmentfault.com/a/1190000004313468

http://blog.csdn.net/lijiecong/article/details/6882267

http://blog.csdn.net/wzyzzu/article/details/50380511

================ End

java监控工具VisualVM的更多相关文章

  1. JAVA 监控工具 VisualVM 插件路径配置地址

    在使用VisualVM监控工具的时候,发现无法安装或者更新插件,或者报错,最后发现原来是插件中心的URL地址原装地址就不对.根据官方网站的地址配置后就正常了.下面的具体地址. VisualVMRele ...

  2. Java监控工具介绍,VisualVm ,JProfiler,Perfino,Yourkit,Perf4J,JProbe,Java微基准测试

    本文是本人前一段时间做一个简单Java监控工具调研总结,主要包括VisualVm ,JProfiler,Perfino,Yourkit,Perf4J,JProbe,以及对Java微基准测试的简单介绍, ...

  3. java自带的监控工具VisualVM(二)远程监控

    ps:尝试了网上的几个网友提供的方法,始终不得其法,汇总后,终于尝试成功!将一些需要注意的细节也记录下来以后备用! 我们经常需要对我们的开发的软件做各种测试, 软件对系统资源的使用情况更是不可少, 目 ...

  4. Java监控工具介绍,VisualVm ,JProfiler,Perfino,Yourkit,Perf4J,JProbe,Java微基准测试【转】

    Java监控工具介绍,VisualVm ,JProfiler,Perfino,Yourkit,Perf4J,JProbe,Java微基准测试[转] 本文是本人前一段时间做一个简单Java监控工具调研总 ...

  5. Java性能监控工具:VisualVM

    VisualVM是JDK自带的一款全能型性能监控和故障分析工具,包括对CPU使用.JVM堆内存消耗.线程.类加载的实时监控,内存dump文件分析,垃圾回收运行情况的可视化分析等,对故障排查和性能调优很 ...

  6. java自带的监控工具VisualVM一

    转自:http://www.cnblogs.com/wade-xu/p/4369094.html 这篇总结的很不错(本人亲自操手学习),留着以后复习备用,很适合入门级的学习者: VisualVM 是一 ...

  7. 使用Java监控工具出现 Can't attach to the process

    问题重现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ➜ jinfo -flags 3032 Attaching ...

  8. Java监控工具

     1. jmap 查看heapdump 2. jstack         查看javacore 3.jps        列出jvm进程 4.jstatd      启动jvm监控服务.它是一个基于 ...

  9. 010-JDK可视化监控工具-VisualVM

    一.概述 VisualVM是一个集成多个JDK命令行工具的可视化工具.VisualVM基于NetBeans平台开发,它具备了插件扩展功能的特性,通过插件的扩展,可用于显示虚拟机进程及进程的配置和环境信 ...

随机推荐

  1. pandas:解决groupby().apply()方法打印两次

    对于以下dataframe执行dataframe.groupby(['name', 'course']).apply(lambda x: test(x)) 操作 其中test(x)函数为: def t ...

  2. ORA-12638:Credential retrieval failed(身份证明检索失败)解决方法

    版本:oracle 11g 解决方法: 在sqlnet.ora中设置SQLNET.AUTHENTICATION_SERVICES= 0.本人亲自验证,可以解决此问题. 网上说设置SQLNET.AUTH ...

  3. 20min 快速着手Markdown

    目录 Markdown介绍和基本使用 初步介绍 markdown的使用场景 为什么是 Markdown markdown的基本语法和使用平台 Q&A: Markdown介绍和基本使用 初步介绍 ...

  4. MariaDB 安装与启动 过程记录

    1. 安装之前的准备工作 rpm -qa |grep mysql rpm -qa |grep mariadb 按照查出来的软件包使用  yum remove  全部卸载,当然也可以 yum remov ...

  5. 太白教你学python---博客分类目录

    太白非技术类随笔(持续更新中...猛击这里!!!) python基础 python基础一 pytcharm安装详细教程 python基础二 python基础数据类型 Python最详细,最深入的代码块 ...

  6. ZJOI2008 生日聚会Party

    对于任意连续区间的限制,可以转化为以i结尾的所有区间的限制.这个转换在昨天的后缀自动机题也有用到,因此将其命名为区后变换.稍加分析后,我们记录以i结尾任意区间最大差即可进行DP转移.这个转换同时也创造 ...

  7. 12.16 Daily Scrum

      Today's Task Tomorrow's Task 丁辛 实现和菜谱相关的餐厅列表. 实现和菜谱相关的餐厅列表.             邓亚梅             美化搜索框UI. 美 ...

  8. first time to use github

    first time to use github and feeling good. 学习软件工程,老师要求我们用这个软件管理自己的代码,网站是全英的,软件也简单易用,方便 https://githu ...

  9. 第七组团队项目——专业课程资源共享平台——需求分析&原型设计

    一.项目目标.定位需求: (1)目标:在教师.学生之间建立一个综合的.全面的.快捷的.高效的免费课程和学习资源共享.交流与推荐的开放性平台,实现多维和动态的推荐与分类检索服务. (2)定位:学生与教师 ...

  10. QT 窗口置顶功能

    Qt中,保持窗口置顶的设置为: Qt::WindowFlags m_flags = windowFlags(); setWindowFlags(m_flags | Qt::WindowStaysOnT ...