性能分析神器VisualVM【转】

Posted on 2015-04-17 09:37 WadeXu 阅读(5809) 评论(6) 编辑 收藏

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

目录:
准备工作
内存分析篇
内存堆Heap
永久保留区域PermGen
CPU分析篇
线程分析篇
参考文献

准备工作

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

内存分析篇

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

1)内存堆Heap

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

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

程序如下:

package jvisualVM;

public class JavaHeapTest {
public final static int OUTOFMEMORY = 200000000; private String oom; private int length; StringBuffer tempOOM = new StringBuffer(); public JavaHeapTest(int leng) {
this.length = leng; int i = 0;
while (i < leng) {
i++;
try {
tempOOM.append("a");
} catch (OutOfMemoryError e) {
e.printStackTrace();
break;
}
}
this.oom = tempOOM.toString(); } public String getOom() {
return oom;
} public int getLength() {
return length;
} public static void main(String[] args) {
JavaHeapTest javaHeapTest = new JavaHeapTest(OUTOFMEMORY);
System.out.println(javaHeapTest.getOom().length());
} }

查看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使用情况

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

package jvisualVM;

import java.io.File;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List; public class TestPermGen { private static List<Object> insList = new ArrayList<Object>(); public static void main(String[] args) throws Exception { permLeak();
} private static void permLeak() throws Exception {
for (int i = 0; i < 1000; i++) {
URL[] urls = getURLS();
URLClassLoader urlClassloader = new URLClassLoader(urls, null);
Class<?> logfClass = Class.forName("org.apache.commons.logging.LogFactory", true,urlClassloader);
Method getLog = logfClass.getMethod("getLog", String.class);
Object result = getLog.invoke(logfClass, "TestPermGen");
insList.add(result);
System.out.println(i + ": " + result);
}
} private static URL[] getURLS() throws MalformedURLException {
File libDir = new File("C:/Users/wadexu/.m2/repository/commons-logging/commons-logging/1.1.1");
File[] subFiles = libDir.listFiles();
int count = subFiles.length;
URL[] urls = new URL[count];
for (int i = 0; i < count; i++) {
urls[i] = subFiles[i].toURI().toURL();
}
return urls;
} }

一个类型装载之后会创建一个对应的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/

通过本文的介绍,相信读者已经对性能分析有一个初步的了解了,如果您觉得本文的内容对您的学习有所帮助,您可以点击右下方的推荐按钮,您的鼓励是我创作的动力。

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

Teaching is learning.

性能分析神器VisualVM【转】的更多相关文章

  1. Java性能分析神器--VisualVM Launcher[1]

    Java性能分析神器1--VisualVM Launcher VisualVM 当你日复一日敲代码的时候,当你把各种各样的框架集成到一起的时候,看着大功告成成功运行的日志,有没有那么一丝丝迷茫和惆怅: ...

  2. 性能分析神器VisualVM

    VisualVM 是一款免费的,集成了多个 JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优.这些功能包括生成和分析海量数据.跟踪内存泄漏.监控垃圾回 ...

  3. Java性能分析神器-JProfiler详解(一)(转)

    前段时间在给公司项目做性能分析,从简单的分析Log(GC log, postgrep log, hibernate statitistic),到通过AOP搜集软件运行数据,再到PET测试,感觉时间花了 ...

  4. Java性能分析神器-JProfiler详解(转)

    前段时间在给公司项目做性能分析,从简单的分析Log(GC log, postgrep log, hibernate statitistic),到通过AOP搜集软件运行数据,再到PET测试,感觉时间花了 ...

  5. Intellij IDEA集成JProfiler性能分析神器

    环境 JProfiler 17.1.3(IDEA插件) JProfiler 9.2(可执行软件) IntelliJ IDEA 2017.2.5 下载 下载JProfiler(IDEA)插件 方式1: ...

  6. Node.js性能分析神器Easy-Monitor

    摘要: 使用Easy-Monitor,可以准确定位Node.js应用的性能瓶颈,帮助我们优化代码性能. 当应用出现性能问题时,最大的问题在于:如何准确定位造成性能瓶颈的代码呢?对于Node.js开发者 ...

  7. Windows平台下,Java性能分析工具VisualVM的Tomcat8的配置

    VisualVM在JDK6版本及以上已经自带这个应用. 位置:C:\Program Files (x86)\Java\jdk1.8.0_60\bin\jvisualvm.exe   在Windows环 ...

  8. 性能测试三十八:Java性能分析神器-JProfiler安装和简单介绍

    Jprofiler是一个重量级的工具,需要分别在服务器和windows都装客户端,会损耗性能,用于发现问题后排查问题,而不是常规的监控 JPROFILER工具下载地址:http://www.ej-te ...

  9. 性能分析工具VisualVM for eclipse安装过程总结

    Java VisualVM Java VisualVM is a tool that provides a visual interface for viewing detailed informat ...

随机推荐

  1. Java--下大雪模拟

    package firstpack; import java.awt.*; public class MyStar { public static void main(String[] args) { ...

  2. ionic:temple

    ylbtech-ionic:temple 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   作者:ylbtech出处:http://ylb ...

  3. 配置基于Devstack的嵌套KVM虚拟化

    本文为minxihou的翻译文章,转载请注明出处Bob Hou: http://blog.csdn.net/minxihou JmilkFan:minxihou的技术博文方向是 算法&Open ...

  4. Portainer Exec Container 失败解决方案

    近日,将portainer服务挂了个域名,然后用Nginx代理的时候发现不能attach容器了,经过搜索在issue 找到解决方案 1.修改Nginx config server { listen 8 ...

  5. scrollReveal.js导致页面加载完之后页面中点击事件添加的css参数失效了(我的Hexo next博客引发的问题)

    文章目录 时间 背景 问题解决 个人博客:https://mmmmmm.me 源码:https://github.com/dataiyangu/dataiyangu.github.io 时间 2019 ...

  6. Codeforces 1167C - News Distribution

    题目链接:http://codeforces.com/problemset/problem/1167/C 题意:大概就是分成几个小团体,给每个人用1 - n编号,当对某个人传播消息的时候,整个小团体就 ...

  7. linux 下安装maven私服

    1.下载最新nexus安装包 下载地址:https://www.sonatype.com/download-oss-sonatype 2.下载JDK7,nexus2版本支持JDK7:nexus1版本支 ...

  8. element-ui的layout将24等分换为48等分

    按住ctr箭点击element-ui/packages/theme-chalk/src/index";,再按住ctr贱点击col.scss跳转,将跳转到的col.scss中的24换为48(c ...

  9. vue使用axios提交formdata格式的数据

    参考: https://www.cnblogs.com/qwert1/p/8909455.html https://blog.csdn.net/qq_42984640/article/details/ ...

  10. Java创建List、Map等集合对象的同时进行赋值操作

    title: Java创建List.Map等集合对象的同时进行赋值操作 date: 2019-11-28 23:25:47 tags: JavaSE categories: JavaSE 问题简介   ...