简介
VisualVM is a visual tool integrating commandline JDK tools and lightweight profiling capabilities.
Designed for both development and production time use.VisualVM 是一款免费的,集成了多个 JDK 命令行工具的可视化工具,它能为您提供强大的分析能力,对 Java 应用程序做性能分析和调优。这些功能包括生成和分析海量数据、跟踪内存泄漏、监控垃圾回收器、执行内存和 CPU 分析,同时它还支持在 MBeans 上进行浏览和操作。本文主要介绍如何使用 VisualVM 进行性能分析及调优。
部分参数说明
Ø 堆 -- 这里要说明下堆内存的组成部分,堆是由老年代和新生代组成,其中新生代有由"伊甸园"和"两个幸存区组成"三部分组成,堆视图看到的资源占用实际是"老年代"、"伊甸园(Eden)"、"两个幸存者(Survivor )"的一个综合情况。
Ø PermGen -- Perm 区用来存放java类以及其他虚拟机自己的静态数据,(常被称为持久代或者方法区)
Ø 类 -- 此视图 主要展示 当前程序加载了多少个类
Ø 线程 -- 当前程序的线程启动情况
§ 执行垃圾回收 -- 手动触发一次GC 相当于在程序代码中调用(System.gc()),如果是远程连接到生产环境中请慎重点击。
§ 堆Dump -- 生产当前程序的内存快照hprof文件,对于分析内存溢出问题比较有帮助。
(可以查看当前程序内存中的所有对象)
Ø 线程dump – 此按钮主要生产当前程序中所有线程的快照(对分析线程死锁,比较有帮助)
Ø 时间线 – 展示每个线程的实时运行状态(不同颜色代表不同的状态)
内存-> 堆柱状图 – 展示堆内存中各种对象占用的字节数和总实例数
内存->PermGen – 展示方法区各种对象消耗的内存情况
CPU->线程CPU时间 – 主要展示线程消耗的CPU资源信息
添加插件
安装visualgc插件(java.net网站已关闭),插件下载后导入,插件地址:
http://visualvm.github.io/pluginscenters.html
Visual GC(监控垃圾回收器)
有人说“JVM的内存分为两块堆和栈”,还有人说"JVM的内存分为三块(新生代、老年代、方法区)"该有个结论了
对于堆栈说法的人他们是根据下图中的维度来看问题的
要看懂上面的图必须理解Java虚拟机的一些基本概念:
堆(Heap) :JVM管理的内存叫堆
分代:根据对象的生命周期长短,把堆分为3个代:Metaspace,Old和Young,根据不同代的特点采用不同的收集算法,扬长避短也。-
Metaspace(元空间)
元空间是方法区的在HotSpot jvm 中的实现,方法区主要用于存储类的信息、常量池、方法数据、方法代码等。方法区逻辑上属于堆的一部分,但是为了与堆进行区分,通常又叫“非堆”。
元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。,理论上取决于32位/64位系统可虚拟的内存大小。可见也不是无限制的,需要配置参数。
常用配置参数
1.MetaspaceSize初始化的Metaspace大小,控制元空间发生GC的阈值。GC后,动态增加或降低MetaspaceSize。在默认情况下,这个值大小根据不同的平台在12M到20M浮动。使用Java -XX:+PrintFlagsInitial命令查看本机的初始化参数
2.MaxMetaspaceSize
限制Metaspace增长的上限,防止因为某些情况导致Metaspace无限的使用本地内存,影响到其他程序。在本机上该参数的默认值为4294967295B(大约4096MB)。
3.MinMetaspaceFreeRatio
当进行过Metaspace GC之后,会计算当前Metaspace的空闲空间比,如果空闲比小于这个参数(即实际非空闲占比过大,内存不够用),那么虚拟机将增长Metaspace的大小。默认值为40,也就是40%。设置该参数可以控制Metaspace的增长的速度,太小的值会导致Metaspace增长的缓慢,Metaspace的使用逐渐趋于饱和,可能会影响之后类的加载。而太大的值会导致Metaspace增长的过快,浪费内存。
4.MaxMetasaceFreeRatio
当进行过Metaspace GC之后, 会计算当前Metaspace的空闲空间比,如果空闲比大于这个参数,那么虚拟机会释放Metaspace的部分空间。默认值为70,也就是70%。
5.MaxMetaspaceExpansion
Metaspace增长时的最大幅度。在本机上该参数的默认值为5452592B(大约为5MB)。
6.MinMetaspaceExpansion
Metaspace增长时的最小幅度。在本机上该参数的默认值为340784B(大约330KB为)。
-
Tenured(年老代)
年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。 -
Young(年轻代)
年轻代分三个区。一个Eden区,两个Survivor区。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor区也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor复制过来的对象。而且,Survivor区总有一个是空的。
GC的基本概念
gc分为full gc 跟 minor gc,当每一块区满的时候都会引发gc。
-
Scavenge GC
一般情况下,当新对象生成,并且在Eden申请空间失败时,就触发了Scavenge GC,堆Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。 -
Full GC
对整个堆进行整理,包括Young、Tenured和Perm。Full GC比Scavenge GC要慢,因此应该尽可能减少Full GC。有如下原因可能导致Full GC:
-
上一次GC之后Heap的各域分配策略动态变化
-
System.gc()被显示调用
-
Perm域被写满
-
Tenured被写满
内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。其实说白了就是该内存空间使用完毕之后未回收。
jvisualvm和jmc都是JDK自带的监控工具。jmc监控数据比jvisualvm更加丰富。它们都在JDK bin目录中
1. Tomcat环境变量指定的好习惯
安装完Tomcat之后,配置CATALINA_HOME和CATALINA_BASE环境变量,如果需要指定环境变量或者JVM参数值,根据catalina.sh文件中的注释说明单独在setenv.sh或者setenv.bat文件中指定,这样catalina.sh在执行的时候会自动读取。
2. 配置启用Tomcat JMX Remote
Java Visual VM远程监控Tomcat,配置参见:
1 2 3 4 5 6 7 8 |
|
如果authenticate=false的时候不需要配置paasword.file和access.file.否则需要在access.file中指定用户名和读写权限,格式如:
1 2 |
|
password.file中指定用户名和密码,格式如:
1 2 |
|
文档中有个小提示:The password file should be read-only and only accessible by the operating system user Tomcat is running as. (意思是password.file的读写权限是400,仅运行tomcat服务的操作系统用户可以访问)
服务器上启动Tomcat,本地运行jvisual.exe配置JMX,连接远程Tomcat进行监控。
接下来介绍另一个JDK自带的监控工具jmc,打开bin/jmc.exe 之后,jmc即可扫描出本地运行的JVM进程
选择一个进程,点开选择MBean服务器,右键 启动JMX控制台,即可看到监控信息
如果想要用jmc监控远程的JVM进程,配置方式和jvisualvm方式一一样即可。