【JVM 学习笔记 05】:JVM性能调优工具的使用

  • 1、 使用 jstat(命令行工具) 查看线上系统的JVM运行状况
    • 1.1 常用命令
    • 1.2 使用技巧
      • 1.2.1 随着系统运行,每秒钟会在年轻代的Eden区分配多少对象。
      • 1.2.2 Young GC的触发频率和每次耗时
      • 1.2.3 每次Young GC后有多少对象是存活和进入老年代
      • 1.2.4 Full GC的触发时机和耗时
    • 2、使用jmap和jhat摸清线上系统的对象分布
      • 2.1 使用jmap了解系统运行时的内存区域
      • 2.2 使用jmap了解系统运行时的对象分布
      • 2.3 使用jmap生成堆内存转储快照
      • 2.4 使用jhat在浏览器中分析堆转出快照
  • 2、结合工具,从测试到上线:如何分析JVM运行状况及合理优化?
    • 2.1 开发好系统之后的预估性优化
    • 2.2 系统压测时的JVM优化
    • 2.3 对线上系统进行JVM监控
  • 3、案例分析:每秒10万并发的BI系统,如何定位和解决频繁Young GC问题?
  • 4、案例分析:案例实战:每日百亿数据量的实时分析引擎,如何定位和解决频繁Full GC问题?
  • 案例分析...

1、 使用 jstat(命令行工具) 查看线上系统的JVM运行状况

jstat 可以轻易的看到当前运行中的系统,JVM的Eden、Survivor、老年代的内存使用情况,还有Young GC和Full gC的执行 次数以及耗时。
通过这些指标,我们可以轻松的分析出当前系统的运行情况,判断当前系统的内存使用压力以及GC压力,还有就是内存分配是否合理。

1.1 常用命令

  1. jstat -gc PID
    在生产机器 linux上,用jps命令找出 Java进程的PID。
    针对我们的Java进程执行:jstat -gc PID。这就可以看到这个Java进程(其实本质就是一个JVM)的内存和GC情况了。

    运行这个命令之后会看到如下列:
    S0C:这是From Survivor区的大小
    S1C:这是To Survivor区的大小
    S0U:这是From Survivor区当前使用的内存大小
    S1U:这是To Survivor区当前使用的内存大小
    EC:这是Eden区的大小
    EU:这是Eden区当前使用的内存大小
    OC:这是老年代的大小
    OU:这是老年代当前使用的内存大小
    MC:这是方法区(永久代、元数据区)的大小
    MU:这是方法区(永久代、元数据区)的当前使用的内存大小
    YGC:这是系统运行迄今为止的Young GC次数
    YGCT:这是Young GC的耗时
    FGC:这是系统运行迄今为止的Full GC次数
    FGCT:这是Full GC的耗时
    GCT:这是所有GC的总耗时

  2. 其他命令

jstat -gccapacity PID:堆内存分析
jstat -gcnew PID:年轻代GC分析,这里的TT和MTT可以看到对象在年轻代存活的年龄和存活的最大年龄
jstat -gcnewcapacity PID:年轻代内存分析
jstat -gcold PID:老年代GC分析
jstat -gcoldcapacity PID:老年代内存分析
jstat -gcmetacapacity PID:元数据区内存分析

一般来说最完整、最常用、最实用的还是jstat -gc命令,基本 足够我们日常分析jvm的运行情况了。

1.2 使用技巧

我们分析线上的JVM进程,最想要知道的信息包括如下:
新生代对象增长的速率,Young GC的触发频率,Young GC的耗时,每次Young GC后有多少对象是存活下来的,每次Young GC过后有多少对象进入了老年代,老年代对象增长的速率,Full GC的触发频率,Full GC的耗时。

根据这些信息,就可以进行JVMGC优化,合理分配内存空间,尽可能让对象留在年轻 代不进入老年代,避免发生频繁的Full GC。这就是对JVM最好的性能优化了!

1.2.1 随着系统运行,每秒钟会在年轻代的Eden区分配多少对象。

使用命令:

jstat -gc PID 1000 10

每隔1秒钟更新出来最新的一行jstat统计信息,一共执行10次jstat统计。
通过这个命令,你可以非常灵活的对线上机器通过固定频率输出统计信息,观察每隔一段时间的jvm中的Eden区对象占用变化。

这里可以根据自己系统的情况灵活多变的使用,比如你们系统负载很低,不一定每秒都有请求,那么可以把 上面的1秒钟调整为1分钟,甚至10分钟,去看你们系统每隔1分钟或者10分钟大概增长多少对象。

还有就是一般系统都有高峰和日常两种状态,比如系统高峰期用的人很多,此时你就应该在系统高峰期去用上述命令 看看高峰期的对象增长速率。然后你再得在非高峰的日常时间段内看看对象的增长速率。
按照上述思路,基本上你可以对线上系统的高峰和日常两个时间段内的对象增长速率有很清晰的了解。

1.2.2 Young GC的触发频率和每次耗时

多久触发一次Young GC根据系统高峰和日常时候的对象增长速率,那么非常简单就可以推测出来高峰期多久发生一次Young GC,日常期多久发生一次Young GC。

jstat会告诉你迄今为止系统已经发生了多少次Young GC以及这些Young GC的总耗时。也可以推算
比如系统运行24小时后共发生了260次Young GC,总耗时为20s。那么平均下来每次Young GC大概就耗时几十毫秒 的时间。
你大概就知道每次Young GC的时候会导致系统停顿几十毫秒。

1.2.3 每次Young GC后有多少对象是存活和进入老年代

每次Young GC过后有多少对象会存活下来,这个没法直接看出来,但是有办法可以大致推测出来。

之前我们已经推算出来高峰期的时候多久发生一次Young GC,比如3分钟会有一次Young GC,那么此时我们可以执行下述jstat命令:jstat -gc PID 180000 10。这就相当于是让他每隔三分钟执行一次统计,连续 执行10次。

此时大家可以观察一下,每隔三分钟之后发生了一次Young GC,此时Eden、Survivor、老年代的对象变化。
正常来说,Eden区肯定会在几乎放满之后重新变得里面对象很少,比如800MB的空间就使用了几十MB。Survivor区 肯定会放入一些存活对象,老年代可能会增长一些对象占用。所以这里的关键,就是观察老年代的对象增长速率。

从一个正常的角度来看,老年代的对象是不太可能不停的快速增长的,因为普通的系统其实没那么多长期存活的对 象。如果你发现比如每次Young GC过后,老年代对象都要增长几十MB,那很有可能就是你一次Young GC过后存活对象太多了。
存活对象太多,可能导致放入Survivor区域之后触发了动态年龄判定规则进入老年代,也可能是Survivor区域放不下了,所以大部分存活对象进入老年代。

最常见的就是这种情况。如果你的老年代每次在Young GC过后就新增几百KB,或者几MB的对象,这个还算情有可缘,但是如果老年代对象快速增长,那一定是不正常的。
所以通过上述观察策略,你就可以知道每次Young GC过后多少对象是存活的,实际上Survivor区域里的和进入老年代的对象,都是存活的。
你也可以知道老年代对象的增长速率,比如每隔3分钟一次Young GC,每次会有50MB对象进入老年代,这就是年代 对象的增长速率,每隔3分钟增长50MB。

1.2.4 Full GC的触发时机和耗时

只要知道了老年代对象的增长速率,那么Full GC的触发时机就很清晰了,比如老年代总共有800MB的内存,每隔3分 钟新增50MB对象,那么大概每小时就会触发一次Full GC。

然后可以看到jstat打印出来的系统运行起劲为止的Full GC次数以及总耗时,比如一共执行了10次Full GC,共耗时 30s,每次Full GC大概就是需要耗费3s左右。

2、使用jmap和jhat摸清线上系统的对象分布

2.1 使用jmap了解系统运行时的内存区域

有的时候可能我们会发现JVM新增对象的速度很快,然后就想要去看看,到底什么对象占据了那么多的内存。
如果发现有的对象在代码中可以优化一下创建的时机,避免那种对象对内存占用过大,那么也许甚至可以去反过来优化一下代码。
当然,其实如果不是出现OOM那种极端情况,也并没有那么大的必要去着急优化代码。

命令:

jmap -heap PID

这个命令可以打印出来一系列的信息,大致来说,这个信息会打印出来堆内存相关的一些参数设置,然后就是当前堆内存里的一些基本各个区域的情况。
比如Eden区总容量、已经使用的容量、剩余的空间容量,两个Survivor区的总容量、已经使用的容量和剩余的空间容量,老年代的总容量、已经使用的容量和剩余的容量。
这些信息jstat已经有了,所以一般不会用jmap去看这些信息,因为没有gc 相关的统计。

2.2 使用jmap了解系统运行时的对象分布

jmap -histo PID

这个命令会打印出来类似下面的信息:

他会按照各种对象占用内存空间的大小降序排列,把占用内存最多的对象放在最上面。
所以如果你只是想要简单的了解一下当前jvm中的对象对内存占用的情况,只要直接用jmap -histo命令即可,非常好用
可以快速了解到当前内存里到底是哪个对象占用了大量的内存空间。

2.3 使用jmap生成堆内存转储快照

可以用jmap命令生成一个堆内存快照放到一个文件里去,用如下的命令即可:

jmap -dump:live,format=b,file=dump.hprof PID

这个命令会在当前目录下生成一个dump.hrpof文件,这里是二进制的格式,不能直接打开看,他把这一时刻JVM堆内存里所有对象的快照放到文件里去了,供你后续去分析。

2.4 使用jhat在浏览器中分析堆转出快照

接着就可以使用 jhat 去分析堆快照了,jhat 内置了web服务器,他会支持你通过浏览器来以图形化的方式分析堆转储快照
使用如下命令即可启动jhat服务器,还可以指定自己想要的http端口号,默认是7000端口号:

jhat dump.hprof -port 7000

接着在浏览器上访问当前这台机器的7000端口号,就可以通过图形化的方式去分析堆内存里的对象分布情况了。

2、结合工具,从测试到上线:如何分析JVM运行状况及合理优化?

2.1 开发好系统之后的预估性优化

在系统开发完毕之后,实际上各位同学就应该参照之前我们多个案例中介绍的思路,对系统进行预估性的优化。

自行估算系统每秒大概多少请求,每个请求会创建多少对象,占用多少内存,机器应该选用什么样的配 置,年轻代应该给多少内存,Young GC触发的频率,对象进入老年代的速率,老年代应该给多少内存,Full GC触发的频率。
这些东西其实是可以根据自己写的代码,大致合理的预估一下的。

在预估完成之后,就可以采用之前多个案例介绍的优化思路,先给自己的系统设置一些初始性的JVM参数
比如堆内存大小,年轻代大小,Eden和Survivor的比例,老年代的大小,大对象的阈值,大龄对象进入老年代的阈值,等等。

优化思路其实简单来说就一句话:尽量让每次Young GC后的存活对象小于Survivor区域的50%,都留存在年轻代里。尽量别让对象 进入老年代。尽量减少Full GC的频率,避免频繁Full GC对JVM性能的影响。

2.2 系统压测时的JVM优化

通常一个新系统开发完毕之后,就会经过一连串的测试。从本地的单元测试,到系统集成测试,再到测试环境的功能测试,预发布环境的压力测试,要保证系统的功能全部正常。而且在一定压力下性能、稳定性和并发能力都正常,最后才会部署到生产环境运行。

这里非常关键的一个环节就是预发布环境的压力测试,通常在这个环节,会使用一些压力测试工具模拟比如1000个用户同时访问系 统,造成每秒500个请求的压力,然后看系统能否支撑住每秒500请求的压力。同时看系统各个接口的响应延时是否在比如200ms之 内,也就是接口性能不能太慢,或者是在数据库中模拟出来百万级单表数据,然后看系统是否还能稳定运行。

具体如何进行系统压测有很多开源的工具,可以轻松模拟 出N个用户同时访问你系统的场景,还能给你一份压力测试报告,告诉你系统可以支撑每秒多少请求,包括系统接口的响应延时。
在这个环节,通常压测工具会对系统发起持续不断的请求,持续很长时间,比如几个小时,甚至几天时间。

所以此时,大家完全就可以在这个环节,对测试机器运行的系统,采用jstat工具来分析在模拟真实环境的压力下,JVM的整体运行状 态。
具体如何使用jstat来进行分析,之前都讲的很详细了,包括如何借助jstat的各种功能分析出来以下JVM的关键运行指标:新生代对象 增长的速率,Young GC的触发频率,Young GC的耗时,每次Young GC后有多少对象是存活下来的,每次Young GC过后有多少对象进入了老年代,老年代对象增长的速率,Full GC的触发频率,Full GC的耗时。

然后根据压测环境中的JVM运行状况,如果发现对象过快进入老年代,可能是因为年轻代太小导致频繁Young GC,然 后Young GC的时候很多对象还是存活的,结果Survivor也太小,导致很多对象频繁进入老年代。当然也可能是别的什 么原因。
此时就需要采用之前介绍的优化思路,合理调整新生代、老年代、Eden、Survivor各个区域的内存大小,保证对象尽 量留在年轻代,不要过快进入老年代中。

每个系统都是不一样的,特点不同,复杂度不同。

真正的优化,必须是根据自己的系统,实际观察之后,然后合理调整内存分布,根本没什么固定的 JVM优化模板。
当对压测环境下的系统优化好JVM参数之后,观察Young GC和Full GC频率都很低,此时就可以部署系统上线了。

2.3 对线上系统进行JVM监控

当你的系统上线之后,你就需要对线上系统的JVM进行监控,这个监控通常来说有两种办法。

第一种方法会“low”一些,其实就是每天在高峰期和低峰期都用jstat、jmap、jhat等工具去看看线上系统的JVM运 行是否正常,有没有频繁Full GC的问题。
如果有就优化,没有的话,平时每天都定时去看看,或者每周都去看看即可。

第二种方法在中大型公司里会多一些,大家都知道,很多中大型公司都会部署专门的监控系统,比较常见的有 Zabbix、OpenFalcon、Ganglia,等等。然后你部署的系统都可以把JVM统计项发送到这些监控系统里去。

此时你就可以在这些监控系统可视化的界面里,看到你需要的所有指标,包括你的各个内存区域的对象占用变化曲 线,直接可以看到Eden区的对象增速,还会告诉你Young GC发生的频率以及耗时,包括老年代的对象增速以及Full GC的频率和耗时。

而且这些工具还允许你设置监控。也就是说,你可以指定一个监控规则,比如线上系统的JVM,如果10分钟之内发生5 次以上Full GC,就需要发送报警给你。比如发送到你的邮箱、短信里,这样你就不用自己每天去看着了。

但是这些监控工具的使用不在我们专栏范畴里,因为这些内容并不一定每个公司都一样,也不一定每个公司都有。比如“OpenFalcon监控JVM”,会看到很多资料。

简单一句话总结:对线上运行的系统,要不然用命令行工具手动监控,发现问题就优化,要不然就是依托公司的监控 系统进行自动监控,可视化查看日常系统的运行状态。

3、案例分析:每秒10万并发的BI系统,如何定位和解决频繁Young GC问题?

4、案例分析:案例实战:每日百亿数据量的实时分析引擎,如何定位和解决频繁Full GC问题?

案例分析…

【JVM 学习笔记 05】:JVM性能调优工具的使用和优化案例相关推荐

  1. golang学习笔记——测试与性能调优

    测试 longestString/longestString.go package main//Nonrepeating : method of double points(双指针法) func No ...

  2. JVM性能调优(4)——性能调优工具

    目录 一.JDK工具1.JDK工具2.利用 jps 找出进程3.利用 jstat 查看VM统计信息4.利用 jmap 查看对象分布情况5.利用 jstack 分析线程栈 二.Linux 命令行工具1. ...

  3. jvm性能调优工具之 jmap使用详解

    本文来说下jvm性能调优工具之 jmap使用详解 文章目录 概述 jmap用法 示例一:no option 示例二:heap 示例三:histo[:live] 示例四:clstats 示例五:fina ...

  4. JVM性能调优监控工具专题一:JVM自带性能调优工具(jps,jstack,jmap,jhat,jstat,hprof)...

    2019独角兽企业重金招聘Python工程师标准>>> 前提概要:         JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外 ...

  5. Java应用性能调优工具介绍及实践

    一.背景 (1).随着微服务架构的逐渐推广,一个大型的单个应用程序被拆分为数个微服务系统,这为研发人员的本地调试跟踪带来困难 (2).在微服务架构中,由于业务的复杂性,常常一个业务流程涉及好数个微服务 ...

  6. java 性能 火焰图_性能调优工具-火焰图

    性能调优工具-火焰图 发布时间:2019-07-17 19:29, 浏览次数:402 前言 工具的进化一直是人类生产力进步的标志,合理使用工具能大大提高我们的工作效率,遇到问题时,合理使用工具更能加快 ...

  7. Go性能调优及相关工具使用(四)——性能调优工具pprof的使用

    文章目录 一.本次学习重点内容: 本堂课的知识要点有哪些? 1.性能发现工具pprof 2.性能调优案例 二.详细知识点介绍: 1.性能调优简介 性能调优原则: 2.性能发现工具pprof 说明: p ...

  8. vmstat、uptime、mpstat-CPU性能调优工具

    vmstat-CPU性能调优工具 vmstat vmstat命令的语法和参数 uptime mpstat 安装sysstat工具包 语法和参数 vmstat vmstat是VirtualMeomory ...

  9. mysql配置优化ya_mysql性能调优工具之mytop

    Mysql性能调优工具之mytop的安装和使用 1.mytop的下载地址 2.首先安装mytop必要的组件. yum -y install perl-DBD-MySQL perl-DBIperl-Te ...

最新文章

  1. 简单剖析智能指针的思想
  2. 开发人员需知的Web缓存知识(转)
  3. GaussianBlur函数
  4. python3精要(35)-wxPython(1)-简介与开源协议
  5. VTK:图表之ColorVerticesLookupTable
  6. 弥补关系型数据库的不足,引入分布式存储
  7. dell服务器报内存配置不正确,DELL 服务器系统提示错误解决的若干办法
  8. 2018年宝鸡市三检文科数学题目解答
  9. 加速你的vs.net开发环境
  10. spring.profiles.active和spring.profiles.include的使用与区别
  11. 【C语言】判断素数的函数
  12. 信息学奥赛c++ 初学保姆级教程
  13. RQNOJ 34 紧急援救
  14. 高考临近,各地考点附近1公里范围内的酒店房量处于紧张状态
  15. html 悬停 div,关于html:如何在div悬停时影响其他元素
  16. Word中的插入页眉 ?Word中页眉横线如何删除?
  17. gin-gonic/gin使用详解
  18. 请收下这份秘籍: 这里有关于申请 gTech 职位所需知道的一切
  19. 色彩基础-图像处理必备
  20. 菱形程序设计以及宏定义的应用

热门文章

  1. linux,unix,mac osx
  2. 2019/7/2 图书馆检索·真·简陋版(新人学习向)
  3. 弘辽科技:如何制作一个高点击率主图,这些细节一定要记住
  4. 仿六间房网页视频聊天室 网页视频直播系统源码
  5. java仿QQ聊天软件OIM艰辛之路
  6. 在虚拟机上搭建云平台环境(1)Controller和Computer虚拟机的安装
  7. 怎样理解人生观、价值观、世界观?
  8. 鸿蒙系统内存管理,嵌入式系统内存管理-鸿蒙HarmonyOS技术社区-鸿蒙官方战略合作伙伴-51CTO.COM...
  9. 大数据毕业设计 图像检索系统设计与实现
  10. 数据检索---ElasticSerach