性能分析神器VisualVM

article/2025/10/25 3:45:59

性能分析神器VisualVM

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

 

复制代码
目录:准备工作
内存分析篇内存堆Heap永久保留区域PermGenCPU分析篇线程分析篇参考文献
复制代码

 

准备工作

自从 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;}@Overridepublic 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;}@Overridepublic 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.

转载于:https://www.cnblogs.com/qingchen1984/p/4435294.html


http://chatgpt.dhexx.cn/article/qOU3SB4l.shtml

相关文章

VisualVM安装,插件安装,各个面板信息讲解

本篇博文目录: 1.什么是VisualVM2.VisualVM安装3.VisualVM相关说明(各个面板信息)4.VisualVM安装插件(安装GC插件) 1.什么是VisualVM ① VisualVM 提供可视界面&#xff0c;用于查看 JVM运行应用程序的详细信息 ② VisualVM可以提供大量可视化的运行指标,是Java工程师最佳分析工…

java基础工具VisualVM介绍与详细使用

1.美图 2.介绍 官网 : http://visualvm.github.io/ VisualVM是JDK自带的一个用于Java程序性能分析的工具 VisualVM 是一个工具,它提供了一个可视界面,用于查看 Java 虚拟机 (Java Virtual Machine, JVM) 上运行的基于 Java 技术的应用程序(Java 应用程序)的详细信息。您…

VisualVM工具的使用

VisualVM工具的使用 VisualVM&#xff0c;能够监控线程&#xff0c;内存情况&#xff0c;查看方法的CPU时间和内存中的对 象&#xff0c;已被GC的对象&#xff0c;反向查看分配的堆栈(如100个String对象分别由哪几个对象分配出来的)。 VisualVM使用简单&#xff0c;几乎0配置&…

threejs加载obj文件

threejs加载并展示obj文件&#xff1a; 研究了一段时间&#xff0c;总结下&#xff0c;废话少说&#xff0c;直接上代码&#xff1a;<!DOCTYPE html> <html lang"en"><head><title>three.js webgl - loaders - OBJ loader</title><…

Java3D加载obj文件+mtl文件

Java3d入门学习可以参考这位博主大神——苏若年&#xff0c;关于Java3D学习的文章。下面给出他部分文章的链接&#xff1a; 文1 创建三维几何模型:[ http://www.cnblogs.com/dennisit/archive/2013/05/06/3063042.html ] 文2 加载外部Obj模型:[ http://www.cnblogs.com/dennisi…

[OpenGL]导入obj文件

通常来说我们构建一个模型是比较复杂的工作&#xff0c;那么我们还有什么途径获得模型呢。其中一种方法就是导入obj模型&#xff0c;不要被这个名词给吓到了&#xff0c;其实就是把一个制作好的模型保存到一个文件中&#xff0c;我们称为obj文件。 先上图片&#xff1a; 下面说…

vue 加载3D .obj文件

VUE项目 vue-cli 加载obj obj文件存放位置 public/static vue 引入obj 控件&#xff1a;Vue-3D-Model 安装&#xff1a;npm install vue-3d-model <!-- ThreeDCity.vue文件 --> <template><div class"ThreeJSCity"><model-obj class"…

glb转obj文件及构建简单obj文件

目录 一、转换二、构建1三、构建2 一、转换 提供几个转换的网址&#xff1a; https://anyconv.com/glb-to-obj-converter/ https://products.aspose.app/3d/conversion/glb-to-obj https://miconv.com/convert-glb-to-obj/ 二、构建1 自己构建简单obj&#xff1a; 新建文本文…

obj文件(1):obj文件用txt打开并且了解v,f,vn,vt的含义

obj文件:obj文件用txt打开并且了解v,f,vn,vt的含义 笔记obj文件的格式介绍**下载 Blender 软件** 来源&#xff1a;《Computer Graphics Programming in OpenGL Using C 》by V Scott Gordon John L Clevenger内容&#xff1a;介绍obj文件以txt文本形式打开后的标签v,f,vn,vt&a…

什么是obj文件

此文来源&#xff1a;https://www.cnblogs.com/ShadowHanlder/p/4410213.html 百度百科&#xff1a; 程序编译时生成的中间代码文件。目标文件&#xff0c;一般是程序编译后的二进制文件&#xff0c;再通过链接器(LINK.EXE)和资源文件链接就成可执行文件了。OBJ只给出了程序的…

Unity导出模型为Obj文件

Unity导出模型为Obj文件 资源链接下载导入 代码纪要使用方式参考链接 资源链接 原插件代码中只有MeshFilter的Obj导出代码&#xff1b;由于项目需求&#xff0c;需要将SkinnedMeshRenderer导出为Obj文件&#xff0c;故在原代码的基础上&#xff0c;扩展出了SkinnedMeshRendere…

SolidWorks2021导出带材质的OBJ文件

SolidWorks2021导出带材质的OBJ文件 注意SW中所有零件都要使用英文命名&#xff0c;装配体模式下再次新建宏按钮即可 1. 首先下载并安装工具宏 1.1 下载免费工具宏 到Github下载免费的Free-Solidworks-OBJ-Exporter&#xff0c;并解压到自己想要的保存的位置。 1.2 在Soli…

C++/OpenGL 入门(18):读取obj文件并贴图

来源&#xff1a;《Computer Graphics Programming in OpenGL Using C 》by V Scott Gordon John L Clevenger内容&#xff1a;程序6.3 Simple (Limited) OBJ Loader 简单的obj文件读取器&#xff0c;书P152页&#xff0c;PDF171/403 结果 生成&#xff1a; 读取&#xff1a;…

unity动态加载obj文件

unity2018.4.2f1 vs2017 最近项目需求&#xff0c;需要实现动态读物外部obj模型&#xff0c;并加载到场景中&#xff0c;研究了好几天&#xff0c;终于实现了&#xff0c;在此做个记录。 1、首先随便找个.obj模型&#xff0c;带贴图&#xff0c;我的资源截图如下&#xff1a…

obj文件(3): 如何用matlab 打开obj文件

obj文件:如何用 matlab 打开 obj 文件 第一步&#xff1a;检查obj文本格式第二步&#xff1a;用 Blender 软件重新导出obj文件第三步&#xff1a;用excel 打开这个obj 文件第四步&#xff1a;复制excel中的数据&#xff0c;传给matlab第五步&#xff1a; 用matlab 打开3D模型 第…

三维模型obj文件解析

目录 obj文件简介文件结构顶点数据(Vertex data)&#xff1a;自由形态曲线(Free-form curve)/表面属性(surface attributes):元素(Elements):自由形态曲线(Free-form curve)/表面主体陈述(surface body statements):自由形态表面之间的连接(Connectivity between free-form sur…

linux类动态库,Linux动态库(一)

起因 博主在以Linux下做开发。在软件需求中&#xff0c;需要动态库带来的灵活性。 比如说博主主导的智能主机的开发。它需要支持很多种类的设备控制&#xff0c;如普通的开关灯、RGB灯、窗帘、百叶窗等等。我们将这些设备抽象成Device类&#xff0c;具体的设备就从这个类上派生…

OpenFlow Switch

The picture of OpenFlow Switch openflow 架构分为2层&#xff0c;一个是控制器层&#xff0c;一个是switch 层。中间是由openflow protocal进行连接的&#xff0c;负责传输指令与数据。switch分为3大块&#xff0c;第一是openflow channe&#xff0c;他是负责向控制器传输数据…

【博客450】OpenFlow学习

OpenFlow OpenFlow协议规范定义了OpenFlow交换机、流表、OpenFlow通道以及OpenFlow交换协议。 OpenFlow是第一个开放的南向接口协议&#xff0c;也是目前最流行的南向协议。它提出了控制与转发分离的架构&#xff0c;规定了SDN转发设备的基本组件和功能要求&#xff0c;以及与控…

OpenFlow交换机【ACM SIGCOMM顶会论文笔记】

目录 写在前面的话OpenFlow交换机基本思想与工作原理专用OpenFlow交换机&#xff08;Dedicated OpenFlow switches&#xff09; 启用OpenFlow的交换机&#xff08;OpenFlow-enabled switches&#xff09;其他功能&#xff08;Additional features&#xff09;控制器&#xff08…