Java虚拟机深刻理解系列所有文章更新中...html
前面在学习JVM的知识的时候,通常都须要利用相关参数进行分析,而分析通常都须要用到一些分析的工具,由于通常使用IDEA,而VisualVM对于IDEA也不错,因此就选择VisualVM来分析JVM性能,这篇文章就介绍一下如何利用VisualVM进行性能分析,以及在分析以前须要知道一些GC优化的原则,GC优化的目的,以及遇到问题时怎么去解决问题的方法。java
开发大型 Java 应用程序的过程当中不免遇到内存泄露、性能瓶颈等问题,好比文件、网络、数据库的链接未释放,未优化的算法等。随着应用程序的持续运行,可能会形成整个系统运行效率降低,严重的则会形成系统崩溃。为了找出程序中隐藏的这些问题,在项目开发后期每每会使用性能分析工具来对应用程序的性能进行分析和优化。算法
VisualVM 是一款免费的性能分析工具。它经过 jvmstat、JMX、SA(Serviceability Agent)以及 Attach API 等多种方式从程序运行时得到实时数据,从而进行动态的性能分析。同时,它能自动选择更快更轻量级的技术尽可能减小性能分析对应用程序形成的影响,提升性能分析的精度。数据库
这里有两种方式:bash
若是没有按照IDEA插件的话,咱们须要找到JDK的按照目录bin下找到以下执行程序。服务器
而后双击执行,就会出现界面,以下;微信
可是,咱们通常使用IDEA,因此会使用插件,就是下面这种方式。网络
先在插件中找到VisualVM安装;并发
安装了以后,在运行的地方就会多出现两个VisualVM的运行按钮; jvm
这样运行程序以后,就能够自动打开VisualVM程序了。
这一部分先对这个工具作一个简要的介绍,看看基本有哪些咱们会用到的功能。
在没有添加其余插件的时候,是只有下面几个功能的。
如上图所示,概述基本上都是咱们的系统属性、运行程序时设置的JVM参数等信息的展现,因此,这一部分可让咱们查看这些信息。
监视这个界面的功能仍是颇有做用的,能够看到cup运行状况、堆的使用状况、类的状况以及线程的动态状况。
所以,咱们能够利用这个界面查看cpu状况好很差,更重要的是,咱们能够查看堆的使用状况,这对于咱们分析JVM仍是很是重要的。
如上图因此,能够看到全部的线程的状况,是运行、休眠、等待、驻留、监视等状况。
注意, 以上这些都不是关键,关键是VisualVM中还有一个很重要的功能,能够添加插件获取更多的功能。
正是由于有了插件的扩展功能,因此这个工具才如此强大,VisualVM能够作到如下:
在工具->找到可用插件,安装便可。
下一部分咱们就利用已经安装的插件Visual GC
进行分析。
Visual GC
分析虚拟机内存区域这部分会用到一些Java虚拟机的一些基础知识,因此,查看这部分以前,请先查看这篇文章:。
在这个界面分为如下几个部分。
那么知道这些参数以后,怎么去分析虚拟机到底运行是好是坏呢,这个时候,咱们须要了解一些Java虚拟机基础的优化知识。
首先,须要了解一些GC优化的原则。
另外,咱们须要知道咱们GC优化的目的。
通常,咱们须要执行的有如下几点;
至于怎么算合适,后面我会经过一个实例讲解。
其实,若是想要知道更多JVM内存分配和回收策略的原理,能够查看这篇文章:JVM内存分配和回收策略的原理。
通常咱们执行了咱们的程序以后,接下来就是须要查看GC的状态了,接着分析结果,判断是否须要进行优化。
通常若是达到如下的指标,就不须要进行GC了。
Minor GC
执行时间不到50ms
,Minor GC
执行不频繁,约10
秒一次;Full GC
执行时间不到1s
,Full GC
执行频率不算频繁,不低于10
分钟1次;咱们先看一个GC状态须要优化的例子,在这个实例中,咱们给堆分配的最大最小的值都是64M
(很小的堆大小)。
/**
* VM Args:-Xms64m -Xmx64m -XX:+HeapDumpOnOutOfMemoryError
* @author 欧阳思海
*/
public class HeapTest {
static class StaticObject {
}
public static void main(String[] args) {
List<StaticObject> list = new ArrayList<StaticObject>();
int i = 1;
//不断的向堆中添加对象
while (true) {
list.add(new StaticObject());
i++;
System.out.println(i);
System.out.println(list.size());
}
}
}
复制代码
因为分配的堆内存过小,因此致使,堆溢出。
接着咱们查看一下Visual GC
的监视状况。
咱们能够从堆的使用状况看出,基本已经使用完。
从上图可知,在短短的运行时间中,Eden进行了49次GC,虽然时间短,可是能说明一个问题,新生代堆内存分配的空间过小,致使频繁GC。
同时,Old老年代也进行了33次GC,虽然运行时间也在不须要优化的范围内,并且从Survivor能够看出,基本没有GC,说明这些都是大对象,直接进入到了Old老年代,致使GC频繁。
因此,咱们须要进行的优化就是加大新生代和老年代堆内存的大小,同时减小大对象的产生。
咱们将VM参数改成:-Xms512m -Xmx512m -Xmn128m -XX:+HeapDumpOnOutOfMemoryError
,运行大概5分钟再次查看结果。
首先没有出现堆内存溢出。
加大了堆内存,因此堆内存没有出现问题。
加大了堆内存以后,Eden新生代进行了66次GC,使用时间3.381s基本知足要求(执行时间不到50ms,Minor GC执行不频繁,约10秒一次),同时老年代old进行了2次GC,使用时间4.127s,这里仍是有待优化的,不太知足优化要求。
点击堆 dump这个按钮就会生成 dump文件,咱们能够分析类及对象的一些状况。
分析以后发现,StaticObject对象大多,没有进行GC,问题主要在这里,因此,下一步须要解决这个问题。
经过以上分析能够说明一个问题,加大了堆内存以后,新生代和老年代的GC状况大大的改善了,可是还有大对象的问题,因此还有待优化。
修改程序,以下:
/** * VM Args:-Xms512m -Xmx512m -Xmn128m -XX:+HeapDumpOnOutOfMemoryError * * @author 欧阳思海 */
public class HeapTest {
/* static class StaticObject { }*/
public static void main(String[] args) {
int i = 1;
while (true) {
i++;
System.out.println(i);
}
}
}
复制代码
堆一直运行良好。
此次相对于上次相比,老年代的状况已经改善了,没有GC,说明大对象不存在了。
经过上面的分析跟优化,就知足GC的需求了,不须要再优化了。
经过上面的分析及使用,VisualVM基本的使用以及如何利用VisualVM进行Java虚拟机优化相信你已经掌握了,若是还想了解更过关于Java虚拟机的知识及优化文章,请看本系列的其余文章。
一、原创不易,老铁,文章须要你的 点赞 让更多的人看到,但愿可以帮助到你们!
二、文章有不当之处,欢迎指正,若是喜欢微信阅读,你也能够关注个人微信公众号:
好好学java
,公众号已有 6W 粉丝,回复:1024,获取公众号的大礼包,公众号长期发布 Java 优质系列文章,关注咱们必定会让你收获不少!