java 高并发GC_深入理解Java虚拟机-如何利用VisualVM对高并发项目进行性能分析

前面在学习JVM的知识的时候,一般都需要利用相关参数进行分析,而分析一般都需要用到一些分析的工具,因为一般使用IDEA,而VisualVM对于IDEA也不错,所以就选择VisualVM来分析JVM性能,这篇文章就介绍一下如何利用VisualVM进行性能分析,以及在分析之前需要知道一些GC优化的原则,GC优化的目的,以及遇到问题时怎么去解决问题的方法。

1 为什么需要

开发大型 Java 应用程序的过程中难免遇到内存泄露、性能瓶颈等问题,比如文件、网络、数据库的连接未释放,未优化的算法等。随着应用程序的持续运行,可能会造成整个系统运行效率下降,严重的则会造成系统崩溃。为了找出程序中隐藏的这些问题,在项目开发后期往往会使用性能分析工具来对应用程序的性能进行分析和优化。

VisualVM 是一款免费的性能分析工具。它通过 jvmstat、JMX、SA(Serviceability Agent)以及 Attach API 等多种方式从程序运行时获得实时数据,从而进行动态的性能分析。同时,它能自动选择更快更轻量级的技术尽量减少性能分析对应用程序造成的影响,提高性能分析的精度。

2 如何安装

这里有两种方式:

没有按照IDEA插件

如果没有按照IDEA插件的话,我们需要找到JDK的按照目录bin下找到如下执行程序。

b89d7c9305b3e2d74bf3405def60c99e.png

然后双击执行,就会出现界面,如下;

194e2e9ee5a0fb5f42406c044b527a5d.png

但是,我们一般使用IDEA,所以会使用插件,就是下面这种方式。

按照IDEA插件

先在插件中找到VisualVM安装;

b07d52e8b6ecc59124cc36c057219319.png

安装了之后,在运行的地方就会多出现两个VisualVM的运行按钮;

c183ce0dc2e2b852ec6570ae706b03a4.png

这样运行程序之后,就可以自动打开VisualVM程序了。

3 基本介绍

这一部分先对这个工具做一个简要的介绍,看看基本有哪些我们会用到的功能。

在没有添加其他插件的时候,是只有下面几个功能的。

55f3723dc10be4c476a64e1e7e8710f1.png

3.1 概述

4a72f1a5253f23fe45d4e3ef7983657c.png

如上图所示,概述基本上都是我们的系统属性、运行程序时设置的JVM参数等信息的展示,所以,这一部分可以让我们查看这些信息。

3.2 监视

653211e215f4fdedc5dd9d8fbcdc4422.png

监视这个界面的功能还是很有作用的,可以看到cup运行情况、堆的使用情况、类的情况以及线程的动态情况。

因此,我们可以利用这个界面查看cpu情况好不好,更重要的是,我们可以查看堆的使用情况,这对于我们分析JVM还是非常重要的。

3.3 线程

01d38007e6ff1401948fcb595af2ea89.png

如上图所以,可以看到所有的线程的情况,是运行、休眠、等待、驻留、监视等情况。

注意, 以上这些都不是关键,关键是VisualVM中还有一个很重要的功能,可以添加插件获取更多的功能。

3.4 插件添加

正是因为有了插件的扩展功能,所以这个工具才如此强大,VisualVM可以做到以下:

显示虚拟机进程以及进程的配置、环境信息、jps、jinfo。

监视应用程序的cpu、GC、堆、方法区以及线程的信息(jstat、jstack)。

dump以及分析堆转存储快照(jmap、jhat)。

还有很多其他的功能。

在工具->找到可用插件,安装即可。

ea48bdd275fa40b8c7dc0fcbab4e2f2b.png

下一部分我们就利用已经安装的插件Visual GC进行分析。

4 利用Visual GC分析虚拟机内存区域

这部分会用到一些Java虚拟机的一些基础知识,所以,查看这部分之前,请先查看这篇文章:。

4ad11e98734cd3f5538200e1498351d5.png

在这个界面分为以下几个部分。

space(Metaspace(元数据)、Old老年代、新生代(Eden、S0、S1))

Graphs(Compile Time(编译时间)、Class Loader Time(类加载时间)、GC Time(垃圾收集时间)、Eden Space、Survivor 0、Survivor 1、Old Gen、Metaspace)

Histogram(Parameters参数设置)

那么知道这些参数之后,怎么去分析虚拟机到底运行是好是坏呢,这个时候,我们需要了解一些Java虚拟机基础的优化知识。

首先,需要了解一些GC优化的原则。

多数的Java应用不需要在服务器上进行GC优化;

多数导致GC问题的Java应用,都不是因为我们参数设置错误,而是代码问题;

在应用上线之前,先考虑将机器的JVM参数设置到最优(最适合);

减少创建对象的数量;

减少使用全局变量和大对象;

GC优化是到最后不得已才采用的手段;

在实际使用中,分析GC情况优化代码比优化GC参数要多得多;

另外,我们需要知道我们GC优化的目的。

将转移到老年代的对象数量降低到最小;

减少full GC的执行时间;

一般,我们需要执行的有以下几点;

减少使用全局变量和大对象;

调整新生代的大小到最合适;

设置老年代的大小为最合适;

选择合适的GC收集器;

至于怎么算合适,后面我会通过一个实例讲解。

其实,如果想要知道更多JVM内存分配和回收策略的原理,可以查看这篇文章:JVM内存分配和回收策略的原理。

一般我们执行了我们的程序之后,接下来就是需要查看GC的状态了,接着分析结果,判断是否需要进行优化。

一般如果达到以下的指标,就不需要进行GC了。

Minor GC执行时间不到50ms,Minor GC执行不频繁,约10秒一次;

Full GC执行时间不到1s,Full GC执行频率不算频繁,不低于10分钟1次;

实例 1

我们先看一个GC状态需要优化的例子,在这个实例中,我们给堆分配的最大最小的值都是64M(很小的堆大小)。

GC状态差情况分析

/**

* VM Args:-Xms64m -Xmx64m -XX:+HeapDumpOnOutOfMemoryError

* @author 欧阳思海

*/

public class HeapTest {

static class StaticObject {

}

public static void main(String[] args) {

List list = new ArrayList();

int i = 1;

//不断的向堆中添加对象

while (true) {

list.add(new StaticObject());

i++;

System.out.println(i);

System.out.println(list.size());

}

}

}

07cf68829b57f81d7abf7eae6719a72b.png

由于分配的堆内存太小,所以导致,堆溢出。

接着我们查看一下Visual GC的监视情况。

监视界面情况

e05221f8ba3d7f385d0d447dc31ad683.png

我们可以从堆的使用情况看出,基本已经使用完。

Visual GC监视情况

ba2b801fc221374553f41c6dc9aea76f.png

从上图可知,在短短的运行时间中,Eden进行了49次GC,虽然时间短,但是能说明一个问题,新生代堆内存分配的空间太小,导致频繁GC。

同时,Old老年代也进行了33次GC,虽然运行时间也在不需要优化的范围内,而且从Survivor可以看出,基本没有GC,说明这些都是大对象,直接进入到了Old老年代,导致GC频繁。

所以,我们需要进行的优化就是加大新生代和老年代堆内存的大小,同时减少大对象的产生。

参数优化分析

我们将VM参数改为:-Xms512m -Xmx512m -Xmn128m -XX:+HeapDumpOnOutOfMemoryError,运行大概5分钟再次查看结果。

300c7c5d8977092885604cc3b158c5d9.png

首先没有出现堆内存溢出。

监视情况

7b1458e1b678fe89ba1ec61eb660dcaa.png

加大了堆内存,所以堆内存没有出现问题。

Visual GC监视情况

2b114ff1bccf99b4496bcb241a9c4af6.png

加大了堆内存之后,Eden新生代进行了66次GC,使用时间3.381s基本满足要求(执行时间不到50ms,Minor GC执行不频繁,约10秒一次),同时老年代old进行了2次GC,使用时间4.127s,这里还是有待优化的,不太满足优化要求。

dump文件分析

386cb2ad802e0b95327bd4722c7a4b6d.png

点击堆 dump这个按钮就会生成 dump文件,我们可以分析类及对象的一些情况。

d30a65e0cfb73d509f5e4be1c0ad5df6.png

分析之后发现,StaticObject对象大多,没有进行GC,问题主要在这里,所以,下一步需要解决这个问题。

通过以上分析可以说明一个问题,加大了堆内存之后,新生代和老年代的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);

}

}

}

监视情况

6be89646ce8d0c0623e59fb030b58999.png

堆一直运行良好。

Visual GC监视情况

a257d440d54a5c79414656cc442c9e73.png

这次相对于上次相比,老年代的情况已经改善了,没有GC,说明大对象不存在了。

通过上面的分析跟优化,就满足GC的需求了,不需要再优化了。

Java虚拟机深入理解系列全部文章更新中...

5 总结

通过上面的分析及使用,VisualVM基本的使用以及如何利用VisualVM进行Java虚拟机优化相信你已经掌握了,如果还想了解更过关于Java虚拟机的知识及优化文章,请看本系列的其他文章。

1、原创不易,老铁,文章需要你的 点赞 让更多的人看到,希望能够帮助到大家!

2、文章有不当之处,欢迎指正,如果喜欢微信阅读,你也可以关注我的微信公众号:好好学java,公众号已有 6W 粉丝。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前 言   致 谢   第一部分 走近Java   第1章 走近Java / 2   1.1 概述 / 2   1.2 Java技术体系 / 3   1.3 Java发展史 / 5   1.4 展望Java技术的未来 / 9   1.4.1 模块化 / 9   1.4.2 混合语言 / 9   1.4.3 多核并行 / 11   1.4.4 进一步丰富语法 / 12   1.4.5 64位虚拟机 / 13   1.5 实战:自己编译JDK / 13   1.5.1 获取JDK源码 / 13   1.5.2 系统需求 / 14   1.5.3 构建编译环境 / 15   1.5.4 准备依赖项 / 17   1.5.5 进行编译 / 18   1.6 本章小结 / 21   第二部分 自动内存管理机制   第2章 Java内存区域与内存溢出异常 / 24   2.1 概述 / 24   2.2 运行时数据区域 / 25   2.2.1 程序计数器 / 25   2.2.2 Java虚拟机栈 / 26   2.2.3 本地方法栈 / 27   2.2.4 Java堆 / 27   2.2.5 方法区 / 28   2.2.6 运行时常量池 / 29   2.2.7 直接内存 / 29   2.3 对象访问 / 30   2.4 实战:OutOfMemoryError异常 / 32   2.4.1 Java堆溢出 / 32   2.4.2 虚拟机栈和本地方法栈溢出 / 35   2.4.3 运行时常量池溢出 / 38   2.4.4 方法区溢出 / 39   2.4.5 本机直接内存溢出 / 41   2.5 本章小结 / 42   第3章 垃圾收集器与内存分配策略 / 43   3.1 概述 / 43   3.2 对象已死? / 44   3.2.1 引用计数算法 / 44   3.2.2 根搜索算法 / 46   3.2.3 再谈引用 / 47   3.2.4 生存还是死亡? / 48   3.2.5 回收方法区 / 50   3.3 垃圾收集算法 / 51   3.3.1 标记 -清除算法 / 51   3.3.2 复制算法 / 52   3.3.3 标记-整理算法 / 54   3.3.4 分代收集算法 / 54   3.4 垃圾收集器 / 55   3.4.1 Serial收集器 / 56   3.4.2 ParNew收集器 / 57   3.4.3 Parallel Scavenge收集器 / 59   3.4.4 Serial Old收集器 / 60   3.4.5 Parallel Old收集器 / 61   3.4.6 CMS收集器 / 61   3.4.7 G1收集器 / 64   3.4.8 垃圾收集器参数总结 / 64   3.5 内存分配与回收策略 / 65   3.5.1 对象优先在Eden分配 / 66   3.5.2 大对象直接进入老年代 / 68   3.5.3 长期存活的对象将进入老年代 / 69   3.5.4 动态对象年龄判定 / 71   3.5.5 空间分配担保 / 73   3.6 本章小结 / 75   第4章 虚拟机性能监控与故障处理工具 / 76   4.1 概述 / 76   4.2 JDK的命令行工具 / 76   4.2.1 jps:虚拟机进程状况工具 / 79   4.2.2 jstat:虚拟机统计信息监视工具 / 80   4.2.3 jinfo:Java配置信息工具 / 82   4.2.4 jmap:Java内存映像工具 / 82   4.2.5 jhat:虚拟机堆转储快照分析工具 / 84   4.2.6 jstack:Java堆栈跟踪工具 / 85   4.3 JDK的可视化工具 / 87   4.3.1 JConsole:Java监视与管理控制台 / 88   4.3.2 VisualVM:多合一故障处理工具 / 96   4.4 本章小结 / 105   第5章 调优案例分析与实战 / 106   5.1 概述 / 106   5.2 案例分析 / 106   5.2.1 高性能硬件上的程序部署策略 / 106   5.2.2 集群间同步导致的内存溢出 / 109   5.2.3 堆外内存导致的溢出错误 / 110   5.2.4 外部命令导致系统缓慢 / 112   5.2.5 服务器JVM进程崩溃 / 113   5.3 实战:Eclipse运行速度调优 / 114   5.3.1 调优前的程序运行状态 / 114   5.3.2 升级JDK 1.6的性能变化及兼容问题 / 117   5.3.3 编译时间和类加载时间的优化 / 122   5.3.4 调

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值