热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

继续谈谈jvm优化必知系列——监控工具

个人博客导航页(点击右侧链接即可打开个人博客):大牛带你入门技术栈  通过上一篇的jvm垃圾回收知识,我们了解了jvm对内存分配以及垃圾回收是

个人博客导航页(点击右侧链接即可打开个人博客):大牛带你入门技术栈 

通过上一篇的jvm垃圾回收知识,我们了解了jvm对内存分配以及垃圾回收是怎么来处理的。理论是指导实践的工具,有了理论指导,定位问题的时候,知识和经验是关键基础,数据可以为我们提供依据。

在常见的线上问题时候,我们多数会遇到以下问题:

  • 内存泄露
  • 某个进程突然cpu飙升
  • 线程死锁
  • 响应变慢...等等其他问题。

如果遇到了以上这种问题,在线下可以有各种本地工具支持查看,但到线上了,就没有这么多的本地调试工具支持,我们该如何基于监控工具来进行定位问题?

我们一般会基于数据收集来定位,而数据的收集离不开监控工具的处理,比如:运行日志、异常堆栈、GC日志、线程快照、堆快照等。经常使用恰当的分析和监控工具可以加快我们的分析数据、定位解决问题的速度。以下我们将会详细介绍。

 

一、jvm常见监控工具&指令

 

1、 jps:jvm进程状况工具

jps [options] [hostid]

 如果不指定hostid就默认为当前主机或服务器。 

 命令行参数选项说明如下: 

-q 不输出类名、Jar名和传入main方法的参数- l 输出main类或Jar的全限名-m 输出传入main方法的参数- v 输出传入JVM的参数

例如:

 


2、jstat: jvm统计信息监控工具

jstat  是用于见识虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、jit编译等运行数据,它是线上定位jvm性能的首选工具。

命令格式:

jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]generalOption - 单个的常用的命令行选项,如-help, -options, 或 -version。outputOptions -一个或多个输出选项,由单个的statOption选项组成,可以和-t, -h, and -J等选项配合使用。

参数选项:

Option

Displays

Ex

class

用于查看类加载情况的统计

jstat -class pid:显示加载class的数量,及所占空间等信息。

compiler

查看HotSpot中即时编译器编译情况的统计

 jstat -compiler pid:显示VM实时编译的数量等信息。 

gc

查看JVM中堆的垃圾收集情况的统计

jstat -gc pid:可以显示gc的信息,查看gc的次数,及时间。其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数,full gc的时间,gc的总时间。 

gccapacity

查看新生代、老生代及持久代的存储容量情况

 jstat -gccapacity:可以显示,VM内存中三代(young,old,perm)对象的使用和占用大小

gccause

查看垃圾收集的统计情况(这个和-gcutil选项一样),如果有发生垃圾收集,它还会显示最后一次及当前正在发生垃圾收集的原因。

jstat -gccause:显示gc原因

gcnew

查看新生代垃圾收集的情况

 jstat -gcnew pid:new对象的信息

gcnewcapacity

用于查看新生代的存储容量情况

  jstat -gcnewcapacity pid:new对象的信息及其占用量

gcold

用于查看老生代及持久代发生GC的情况

jstat -gcold pid:old对象的信息

gcoldcapacity

用于查看老生代的容量

jstat -gcoldcapacity pid:old对象的信息及其占用量

gcpermcapacity

用于查看持久代的容量

jstat -gcpermcapacity pid: perm对象的信息及其占用量

gcutil

查看新生代、老生代及持代垃圾收集的情况

jstat -util pid:统计gc信息统计

printcompilation

HotSpot编译方法的统计

 jstat -printcompilation pid:当前VM执行的信息

例如:

查看gc 情况执行:jstat-gcutil 27777

 

3、jinfo: java配置信息

命令格式:

jinfo[option] pid

比如:获取一些当前进程的jvm运行和启动信息。

 

4、jmap: java 内存映射工具

jmap命令用于生产堆转存快照。打印出某个java进程(使用pid)内存内的,所有‘对象’的情况(如:产生那些对象,及其数量)。

命令格式:

jmap [ option ] pidjmap [ option ] executable corejmap [ option ] [server-id@]remote-hostname-or-IP

 

参数选项:

-dump:[live,]format=b,file= 使用hprof二进制形式,输出jvm的heap内容到文件=. live子选项是可选的,假如指定live选项,那么只输出活的对象到文件. -finalizerinfo 打印正等候回收的对象的信息.-heap 打印heap的概要信息,GC使用的算法,heap的配置及wise heap的使用情况.-histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量. -permstat 打印classload和jvm heap长久层的信息. 包含每个classloader的名字,活泼性,地址,父classloader和加载的class数量. 另外,内部String的数量和占用内存数也会打印出来. -F 强迫.在pid没有相应的时候使用-dump或者-histo参数. 在这个模式下,live子参数无效. -h | -help 打印辅助信息 -J 传递参数给jmap启动的jvm. 

例如:

使用jmap -heap pid查看进程堆内存使用情况,包括使用的GC算法、堆配置参数和各代中堆内存使用情况:

使用jmap -histo[:live] pid查看堆内存中的对象数目、大小统计直方图。

5、jhat:jvm堆快照分析工具

jhat 命令与jamp搭配使用,用来分析map生产的堆快存储快照。jhat内置了一个微型http/Html服务器,可以在浏览器找那个查看。不过建议尽量不用,既然有dumpt文件,可以从生产环境拉取下来,然后通过本地可视化工具来分析,这样既减轻了线上服务器压力,有可以分析的足够详尽(比如 MAT/jprofile/visualVm)等。

6、jstack:java堆栈跟踪工具

jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。

命令格式:

jstack [ option ] pidjstack [ option ] executable corejstack [ option ] [server-id@]remote-hostname-or-IP

 

参数:

-F当’jstack [-l] pid’没有相应的时候强制打印栈信息-l长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表.-m打印java和native c/c++框架的所有栈信息.-h | -help打印帮助信息pid 需要被打印配置信息的java进程id,可以用jps查询.

后续的查找耗费最高cpu例子会用到。

 

二、可视化工具

对jvm监控的常见可视化工具,除了jdk本身提供的Jconsole和visualVm以外,还有第三方提供的jprofilter,perfino,Yourkit,Perf4j,JProbe,MAT等。这些工具都极大的丰富了我们定位以及优化jvm方式。

这些工具的使用,网上有很多教程提供,这里就不再过多介绍了。对于VisualVm来说,比较推荐使用,它除了对jvm的侵入性比较低以外,还是jdk团队自己开发的,相信以后功能会更加丰富和完善。jprofilter对于第三方监控工具,提供的功能和可视化最为完善,目前多数ide都支持其插件,对于上线前的调试以及性能调优可以配合使用。

另外对于线上dump的heap信息,应该尽量拉去到线下用于可视化工具来分析,这样分析更详细。如果对于一些紧急的问题,必须需要通过线上监控,可以采用 VisualVm的远程功能来进行,这需要使用tool.jar下的MAT功能。

 

三、应用

 

1、cpu飙升

在线上有时候某个时刻,可能会出现应用某个时刻突然cpu飙升的问题。对此我们应该熟悉一些指令,快速排查对应代码。

 


1.找到最耗CPU的进程

指令:

top

 

2.找到该进程下最耗费cpu的线程

指令:

top -Hp pid

3.转换进制

printf “%x\n” 15332 // 转换16进制(转换后为0x3be4) 

4.过滤指定线程,打印堆栈信息

指令

jstack pid |grep 'threadPid'  -C5 --color jstack 13525 |grep '0x3be4' -C5 --color // 打印进程堆栈 并通过线程id,过滤得到线程堆栈信息。

可以看到是一个上报程序,占用过多cpu了(以上例子只为示例,本身耗费cpu并不高)

 

2、线程死锁 

有时候部署场景会有线程死锁的问题发生,但又不常见。此时我们采用jstack查看下一下。比如说我们现在已经有一个线程死锁的程序,导致某些操作waiting中。

 


1.查找java进程id

指令:

top 或者 jps 

 

2.查看java进程的线程快照信息

指令:

jstack -l pid

从输出信息可以看到,有一个线程死锁发生,并且指出了那行代码出现的。如此可以快速排查问题。

 

3、OOM内存泄露

java堆内的OOM异常是实际应用中常见的内存溢出异常。一般我们都是先通过内存映射分析工具(比如MAT)对dump出来的堆转存快照进行分析,确认内存中对象是否出现问题。

当然了出现OOM的原因有很多,并非是堆中申请资源不足一种情况。还有可能是申请太多资源没有释放,或者是频繁频繁申请,系统资源耗尽。针对这三种情况我需要一一排查。

 

OOM的三种情况:

1.申请资源(内存)过小,不够用。

2.申请资源太多,没有释放。

3.申请资源过多,资源耗尽。比如:线程过多,线程内存过大等。


 


1.排查申请申请资源问题。

指令:jmap -heap 11869

 查看新生代,老生代堆内存的分配大小以及使用情况,看是否本身分配过小。

从上述排查,发现程序申请的内存没有问题。

2.排查gc

特别是fgc情况下,各个分代内存情况。

指令:jstat -gcutil 11938 1000 每秒输出一次gc的分代内存分配情况,以及gc时间

3.查找最费内存的对象

指令: jmap -histo:live 11869 | more

上述输出信息中,最大内存对象才161kb,属于正常范围。如果某个对象占用空间很大,比如超过了100Mb,应该着重分析,为何没有释放。

 

注意,上述指令:

jmap -histo:live 11869 | more执行之后,会造成jvm强制执行一次fgc,在线上不推荐使用,可以采取dump内存快照,线下采用可视化工具进行分析,更加详尽。jmap -dump:format=b,file=/tmp/dump.dat 11869 或者采用线上运维工具,自动化处理,方便快速定位,遗失出错时间。

 

4.确认资源是否耗尽


  • pstree 查看进程线程数量
  • netstat 查看网络连接数量

或者采用:

  • ll /proc/${PID}/fd | wc -l  // 打开的句柄数
  • ll /proc/${PID}/task | wc -l (效果等同pstree -p | wc -l) //打开的线程数

 

以上就是一些常见的jvm命令应用。

一种工具的应用并非是万能钥匙,包治百病,问题的解决往往是需要多种工具的结合才能更好的定位问题,无论使用何种分析工具,最重要的是熟悉每种工具的优势和劣势。这样才能取长补短,配合使用。

附Java/C/C++/机器学习/算法与数据结构/前端/安卓/Python/程序员必读/书籍书单大全:

(点击右侧 即可打开个人博客内有干货):技术干货小栈
&#61;&#61;&#61;&#61;&#61;>>①【Java大牛带你入门到进阶之路】<<&#61;&#61;&#61;&#61;
&#61;&#61;&#61;&#61;&#61;>>②【算法数据结构&#43;acm大牛带你入门到进阶之路】<<&#61;&#61;&#61;
&#61;&#61;&#61;&#61;&#61;>>③【数据库大牛带你入门到进阶之路】<<&#61;&#61;&#61;&#61;&#61;
&#61;&#61;&#61;&#61;&#61;>>④【Web前端大牛带你入门到进阶之路】<<&#61;&#61;&#61;&#61;
&#61;&#61;&#61;&#61;&#61;>>⑤【机器学习和python大牛带你入门到进阶之路】<<&#61;&#61;&#61;&#61;
&#61;&#61;&#61;&#61;&#61;>>⑥【架构师大牛带你入门到进阶之路】<<&#61;&#61;&#61;&#61;&#61;
&#61;&#61;&#61;&#61;&#61;>>⑦【C&#43;&#43;大牛带你入门到进阶之路】<<&#61;&#61;&#61;&#61;
&#61;&#61;&#61;&#61;&#61;>>⑧【ios大牛带你入门到进阶之路】<<&#61;&#61;&#61;&#61;
&#61;&#61;&#61;&#61;&#61;>>⑨【Web安全大牛带你入门到进阶之路】<<&#61;&#61;&#61;&#61;&#61;
&#61;&#61;&#61;&#61;&#61;>>⑩【Linux和操作系统大牛带你入门到进阶之路】<<&#61;&#61;&#61;&#61;&#61;

天下没有不劳而获的果实&#xff0c;望各位年轻的朋友&#xff0c;想学技术的朋友&#xff0c;在决心扎入技术道路的路上披荆斩棘&#xff0c;把书弄懂了&#xff0c;再去敲代码&#xff0c;把原理弄懂了&#xff0c;再去实践&#xff0c;将会带给你的人生&#xff0c;你的工作&#xff0c;你的未来一个美梦。



推荐阅读
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • 本文介绍了2020年计算机二级MSOffice的选择习题及答案,详细解析了操作系统的五大功能模块,包括处理器管理、作业管理、存储器管理、设备管理和文件管理。同时,还解答了算法的有穷性的含义。 ... [详细]
  • 服务器上的操作系统有哪些,如何选择适合的操作系统?
    本文介绍了服务器上常见的操作系统,包括系统盘镜像、数据盘镜像和整机镜像的数量。同时,还介绍了共享镜像的限制和使用方法。此外,还提供了关于华为云服务的帮助中心,其中包括产品简介、价格说明、购买指南、用户指南、API参考、最佳实践、常见问题和视频帮助等技术文档。对于裸金属服务器的远程登录,本文介绍了使用密钥对登录的方法,并提供了部分操作系统配置示例。最后,还提到了SUSE云耀云服务器的特点和快速搭建方法。 ... [详细]
author-avatar
yklyh
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有