转载:https://www.cnblogs.com/duanxz/p/3713773.html

1.1 Visual VM简介

VisualVM 提供在 Java 虚拟机 (Java Virutal Machine, JVM) 上运行的 Java 应用程序的详细信息。在 VisualVM 的图形用户界面中,您可以方便、快捷地查看多个 Java 应用程序的相关信息。(摘自官方) 简单说来,VisualVM是一种集成了多个JDK命令行工具的可视化工具,它能为您提供强大的分析能力。所有这些都是免费的!它囊括的命令行工具包括jstat, JConsole, jstack, jmap 和 jinfo,这些工具与JDK的标准版本是一致的。 可以使用VisualVM生成和分析海量数据、跟踪内存泄漏、监控垃圾回收器、执行内存和CPU分析,同时它还支持在MBeans上进行浏览和操作。尽管VisualVM自身要在JDK6这个版本上运行,但是JDK1.4以上版本的程序它都能监控。

1.2 如何获取VisualVM

VisualVM的一个最大好处就是,它已经在你的JDK bin目录里了,只要你使用的是JDK1.6 Update7之后的版本。点击一下jvisualvm.exe图标它就可以运行了。

这里是VisualVM 的官方网站:http://visualvm.java.net/download.html,资料很全,同时提供VisualVM最近版本下载。

当然,如果你使用Myeclipse的话,该IDE也集成了对应的工具!

2.1 开启Visual VM之旅

如果你使用的是JDK是1.6Update7之后的版本,那么Visual VM已经包含在bin目录下了,否则需要去官方下载。

2.1.1 启动问题

如果你在windows上使用Visual VM,需要做的只是点一下jvisualvm.exe,就能启动它;绿色,好用。但是Visual VM所在的分区如果是NTFS格式,那么第一个问题就出现了:sun对NTFS格式的硬盘支持有问题!但可通过参数可避免,并完成启动。步骤如下:

1. 创建一个visualvm.exe的快捷方式(或者像上文一样,在MyEclipse中启动)

2. 在“目标”中添加如下参数

-XX:+PerfBypassFileSystemCheck

2.1.2 界面简介

Visual VM启动成功!可以看到Visual VM的界面了。通过Visual VM可以看到本机运行中的所有Java应用。你会发现根本不需要在VisualVM 里为Java应用程序注册,它们就会自动显示出来。甚至还可以在导航栏里查看到远程的Java应用。导航栏即为Applications,其中分为Local(本地Java应用)和Remote(远程Java应用)。

2.1.3 安装插件

Visual VM有很多好用的插件,步骤如下:

1. 点击Tools -> Plugins

2. 推荐安装全部插件

2.2 监控本地Java应用

Visual VM本身就是一个Java应用,所以打开Visual VM看到的第一个可监控应用就是Visual VM本身;可以用它热热身,小试下牛刀。在Visual VM可视化界面中可以监控到Visual VM本身的内存使用情况、线程情况、Jvm启动参数、cpu消耗情况、垃圾回收情况等很多参数。当然如果在本地启一个Tomcat一样可以看到这些参数,可以方便我们在本地对JVM进行调优。但是且接如果你是在windows下起应用,如果你的Java应用是在NTFS格式的盘附上,记得加参数:-XX:+PerfBypassFileSystemCheck

2.2.1 使用Visual VM监测内存泄漏、解决内存溢出问题

2.2.1.1  内存泄露、溢出的异同

同:都会导致应用程序运行出现问题,性能下降或挂起。

异:

1) 内存泄露是导致内存溢出的原因之一;内存泄露积累起来将导致内存溢出。

2) 内存泄露可以通过完善代码来避免;内存溢出可以通过调整配置来减少发生频率,但无法彻底避免。

2.2.1.2  监测内存泄漏

  • 内存泄漏是指程序中间动态分配了内存,但在程序结束时没有释放这部分内存,从而造成那部分内存不可用的情况,重启计算机可以解决,但也有可能再次发生内存泄露,内存泄露和硬件没有关系,它是由软件设计缺陷引起的。

  • 内存泄漏可以分为4类:

1) 常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。

2) 偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。

3) 一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。

4) 隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。

每隔一段时间给所监测的Java应用来一个heap dump,如下面三图所示:

对比上面三个截图,发现似乎有个东西在急速飙升,仔细一看是这个对象:org.eclipse.swt.graphics.Image 在第一章图中这个还没排的上,第二次dump已经上升到5181个,第三次就是7845个了。涨速相当快,而且和任务管理器里面看到的GDI数量增涨一致,就是它了。

问题到这儿就比较清楚了,回到代码里面仔细一看可以发现,是某个地方反复的用图片来创建Image对象导致的,改掉以后搞定问题。

到这里其实我想说的是,Java使用起来其实要比C++更容易导致内存泄漏。对于C++来说,每一个申请的对象都必须明确释放,任何没有释放的对象都会导致memleak,这是不可饶恕的,而且这类问题已经有很多工具和方法来解决。但是到了Java里面情况就不同了,对于Java程序员来说对象都是不需要也无法主动销毁的,所以一般的思路是:随用随new,用完即丢。很多对象具体的生命周期可能连写代码的人自己也不清楚,或者不需要清楚,只知道某个时刻垃圾收集器会去做的,不用管。但很可能某个对象在“用完即丢”的时候在另一个不容易发现的地方被保存了一个引用,那么这个对象就永远不会被回收。更加糟糕的是整个程序从设计之初就没有考虑过对象回收的问题,对于C++程序员来说memleak必然是一个设计错误,但是对Java程序员来说这只是一个疏忽,而且似乎没有什么好的办法来避免。今天看到的这个问题是因为GDI泄漏会造成严重后果才被重视,但如果仅仅是造成内存泄漏,那这个程序可能得连续跑上个十天半个月才会发现问题。最后就是,对于c++,错误的代码在测试阶段就可以快速的侦测出哪怕一个byte的memleak并加以改正,但是对于java程序,理论上没有哪个工具能够知道是不是有泄漏,因为除了作者自己以外没有人能够知道一个被引用的对象是不是应该被销毁,只有通过大量的,长期的压力测试才能发现问题,这是很危险的一件事情。

2.2.1.3  解决内存溢出问题

1、java.lang.OutOfMemoryError: PermGen space

JVM管理两种类型的内存,堆和非堆。堆是在JVM启动时创建;非堆是留给JVM自己用的,用来存放类的信息的。它和堆不同,运行期内GC不会释放空间。如果web app用了大量的第三方jar或者应用有太多的class文件而恰好MaxPermSize设置较小,超出了也会导致这块内存的占用过多造成溢出,或者tomcat热部署时侯不会清理前面加载的环境,只会将context更改为新部署的,非堆存的内容就会越来越多。

PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用中有很CLASS的话,就很可能出现PermGen space错误,这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。

如上图所示,PermGen在程序运行一段时间后超出了我们指定的128MB,通过Classes视图看到,Java在运行的同时加载了大量的类到内存中。PermGen会存储Jar或者Class的描述信息;所以在class大量增加的同时PermGen超出了我们指定的范围。为了让应用稳定,我们需要探寻新的PermGen范围。检测时段时候后(如下图)发现PermGen在145MB左右稳定,那么我们就得到了稳定的新参数;这样PermGen内存溢出的问题得到解决。

2、java.lang.OutOfMemoryError: Java heap space

第一种情况是个补充,主要存在问题就是出现在这个情况中。其默认空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。如果内存剩余不到40%,JVM就会增大堆到Xmx设置的值,内存剩余超过70%,JVM就会减小堆到Xms设置的值。所以服务器的Xmx和Xms设置一般应该设置相同避免每次GC后都要调整虚拟机堆的大小。假设物理内存无限大,那么JVM内存的最大值跟操作系统有关,一般32位机是1.5g到3g之间,而64位的就不会有限制了。

注意:如果Xms超过了Xmx值,或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。

垃圾回收GC的角色,JVM调用GC的频度还是很高的,主要两种情况下进行垃圾回收:

一个是当应用程序线程空闲;另一个是java内存堆不足时,会不断调用GC,若连续回收都解决不了内存堆不足的问题时,就会报out of memory错误。因为这个异常根据系统运行环境决定,所以无法预期它何时出现。

根据GC的机制,程序的运行会引起系统运行环境的变化,增加GC的触发机会。

为了避免这些问题,程序的设计和编写就应避免垃圾对象的内存占用和GC的开销。显示调用System.GC()只能建议JVM需要在内存中对垃圾对象进行回收,但不是必须马上回收。一个是并不能解决内存资源耗空的局面,另外也会增加GC的消耗。

如上图所示,used heap的折线图呈峰状,说明垃圾对象及时被回收了,内存得以释放。如果used heap的值只增不减说明存在内存泄漏了,如果超过heap size的值,会报内存溢出的错误。

2.2.1.4  如何避免内存泄漏、溢出

1) 尽早释放无用对象的引用。

好的办法是使用临时变量的时候,让引用变量在退出活动域后自动设置为null,暗示垃圾收集器来收集该对象,防止发生内存泄露。

2) 程序进行字符串处理时,尽量避免使用String,而应使用StringBuffer。

因为每一个String对象都会独立占用内存一块区域,如:

  1. String str = "aaa";

  2. String str2 = "bbb";

  3. String str3 = str + str2;

  4. // 假如执行此次之后str , str2再不被调用,那么它们就会在内存中等待GC回收;

  5. // 假如程序中存在过多的类似情况就会出现内存错误;

3) 尽量少用静态变量。

因为静态变量是全局的,GC不会回收。

4) 避免集中创建对象尤其是大对象,如果可以的话尽量使用流操作。

JVM会突然需要大量内存,这时会触发GC优化系统内存环境; 一个案例如下:

很久以前,使用jspsmartUpload作文件上传,现在运行过程中经常出现java.outofMemoryError的错误,用top命令看看进程使用情况,发现内存不足2M,花了很长时间,发现是jspsmartupload的问题。把jspsmartupload组件的源码文件(class文件)反编译成Java文件,如梦方醒: 
m_totalBytes = m_request.getContentLength();

m_binArray = new byte[m_totalBytes];

变量m_totalBytes表示用户上传的文件的总长度,这是一个很大的数。如果用这样大的数去声明一个byte数组,并给数组的每个元素分配内存空间,而且m_binArray数组不能马上被释放,JVM的垃圾回收确实有问题,导致的结果就是内存溢出。

jspsmartUpload为什末要这样作,有他的原因,根据RFC1867的http上传标准,得到一个文件流,并不知道文件流的长度。设计者如果想文件的长度,只有操作servletinputstream一次才知道,因为任何流都不知道大小。只有知道文件长度了,才可以限制用户上传文件的长度。为了省去这个麻烦,jspsmartUpload设计者直接在内存中打开文件,判断长度是否符合标准,符合就写到服务器的硬盘。这样产生内存溢出,这只是我的一个猜测而已。

所以编程的时候,不要在内存中申请大的空间,因为web服务器的内存有限,并且尽可能的使用流操作,例如

byte[] mFileBody = new byte[512];
        Blob vField= rs.getBlob("FileBody"); 
     InputStream instream=vField.getBinaryStream();
     FileOutputStream fos=new FileOutputStream(saveFilePath+CFILENAME);
         int b;
                      while( (b =instream.read(mFileBody)) != -1){
                       fos.write(mFileBody,0,b);
                        }
       fos.close();
     instream.close();

5) 尽量运用对象池技术以提高系统性能。

生命周期长的对象拥有生命周期短的对象时容易引发内存泄漏,例如大集合对象拥有大数据量的业务对象的时候,可以考虑分块进行处理,然后解决一块释放一块的策略。

6) 不要在经常调用的方法中创建对象,尤其是忌讳在循环中创建对象。

可以适当的使用hashtable,vector 创建一组对象容器,然后从容器中去取那些对象,而不用每次new之后又丢弃。

7) 优化配置。

1、 设置-Xms、-Xmx相等;

2、 设置NewSize、MaxNewSize相等;

3、 设置Heap size, PermGen space:

Tomcat 的配置示例:修改 %TOMCAT_HOME%/bin/catalina.bat or catalina.sh

在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:

set JAVA_OPTS=-Xms800m -Xmx800m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m

jdk连结tomcat参考资料:

https://blog.csdn.net/qq_38078607/article/details/80459167

一、jdk工具之jps(JVM Process Status Tools)命令使用

二、jdk命令之javah命令(C Header and Stub File Generator)

三、jdk工具之jstack(Java Stack Trace)

四、jdk工具之jstat命令(Java Virtual Machine Statistics Monitoring Tool)

五、jdk工具之jmap(java memory map)、 mat之四--结合mat对内存泄露的分析

六、jdk工具之jinfo命令(Java Configuration Info)

七、jdk工具之jconsole命令(Java Monitoring and Management Console)

八、jdk工具之JvisualVM、JvisualVM之二--Java程序性能分析工具Java VisualVM

九、jdk工具之jhat命令(Java Heap Analyse Tool)

十、jdk工具之Jdb命令(The Java Debugger)

十一、jdk命令之Jstatd命令(Java Statistics Monitoring Daemon)

jdk工具之JvisualVM、JvisualVM之一--(visualVM介绍及性能分析示例)相关推荐

  1. java c 性能分析工具_Jprofiler使用介绍--java性能分析工具中文帮助

    1.说明 改善Java服务器的性能需要模拟负载下的服务器.创建一个模拟环境.搜集数据并且分析结果可能是对许多开发人员的挑战.这里介绍了使用JProfiler跟踪分析Java服务器的性能. 简单的性能问 ...

  2. java visualvm 教程_Java性能分析神器--VisualVM Launcher[1]

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

  3. Java VisualVM(Java性能分析工具)插件安装及JDK版本对应插件中心地址

    参考文章: VisualVM(3) 插件安装与更新路径配置 Java VisualVM插件地址 安装jvisualvm的时候,发现插件可用为0,错误提示"连接插件中心超时".上网查 ...

  4. Dijkstra算法介绍+正确性证明+性能分析

    算法介绍 源点s,数组d[u]表示s到u的最短距离,空集S,点集Q 初始化:将源点s从点集中去掉,加入S,d[s]=0,∀v∈Q,d[v]=w[s][v]\forall v\in Q ,d[v]=w[ ...

  5. VisualVM——JDK自带的性能分析工具

    引子 这段时间项目新版本要发了,所以跟着QA分析性能测试和压力测试,用了平时不怎么用的很多工具: jmap jmap -heap pid → 查看堆的使用状况信息  jmap -histo:live ...

  6. 性能分析利器总结一《VisualVM》

    VisualVM 随着JDK7而出现,位于JDK根目录下的bin目录下.运行环境需JDK1.6及以上,能监控JDK1.4以上版本的应用程序. 相比JConsole,感觉功能更强大,且可集成各类插件,使 ...

  7. JVM虚拟机学习 - JVM类加载,JVM内存模型,JVM性能分析工具

    JVM虚拟机 二 JVM类加载 类的生命周期 加载: ​ 加载class文件到二进制字节流,然后再将二进制字节流转化为方法区的运行时数据结构,生成一个对应的Class对象作为类各种数据的访问入口. 链 ...

  8. Linux性能分析命令工具汇总

    转自:http://rdc.hundsun.com/portal/article/731.html?ref=myread 出于对Linux操作系统的兴趣,以及对底层知识的强烈欲望,因此整理了这篇文章. ...

  9. .NET 11 个 Visual Studio 代码性能分析工具

    原文地址 软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行 ...

最新文章

  1. 切割图形_重庆Q3245R锅炉板加工几何图形2021新闻
  2. 服务器客户端回射程序-自己设计包的结构
  3. C++标准pdf 分享
  4. KillTimer()的使用
  5. java学习--基础知识第六天--笔记
  6. 回文字符串—回文子串—中心扩散法
  7. flutter 返回指定界面_Flutter页面路由导航及传参
  8. Paddle 使用预训练模型 实现快递单信息抽取
  9. 统计方形++(洛谷P2241题题解,Java语言描述)
  10. c#操作ecxel的一些资源(downmoon搜集)
  11. linuxc网络通信
  12. python绘制音频频谱_Python 读取wav画频谱
  13. OSChina 周五乱弹 —— 闹钟一响就睡觉
  14. 网站被黑提醒该站点可能受到黑客攻击,部分页面已被非法篡改...
  15. 押上声誉百亿豪赌,雷军几分胜算?
  16. mixly红外遥控问题在线等
  17. esim卡与ms卡的区别_什么是eSIM,它与SIM卡有何不同?
  18. ps2口键盘改usb计算机设置,轻松把PS2键盘、鼠标接口改造成USB接口
  19. 区块链论文8(ContractGuard分析写作手法)
  20. Win7 10安装Office2010提示让安装MSXML组件的五种解决方法

热门文章

  1. Qt编写可视化大屏电子看板系统22-平滑曲线图
  2. 一个程序怎么跑起来的
  3. Subdomain of Voice Synsthesis 声音合成简介
  4. 【无标题】CINTA第五次作业 同构
  5. 迅雷特殊功能令下载速度提高
  6. 【HDOJ】 1001 Sum Problem_天涯浪子_新浪博客
  7. Android Room 使用指南
  8. ABB 510变频器配合MCGS实现恒压供水控制程序 比起单变频器实现恒压供水,配合触摸屏可以让数据更加直观
  9. mysql 餐饮管理系统_餐饮管理系统的设计与实现(MySQL)
  10. MATLAB:OFDM_256QAM_100MHz