jStat

JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、jinfo、jconsole使用详解

…衆ロ難τιáo~ 提交于 2020-04-25 08:29:05
JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps、jstack、jmap、jhat、jstat等小巧的工具,本博客希望能起抛砖引玉之用,让大家能开始对JVM性能调优的常用工具有所了解。 现实企业级Java开发中,有时候我们会碰到下面这些问题: OutOfMemoryError,内存不足 内存泄露 线程死锁 锁争用(Lock Contention) Java进程消耗CPU过高 ...... 这些问题在日常开发中可能被很多人忽视(比如有的人遇到上面的问题只是重启服务器或者调大内存,而不会深究问题根源),但能够理解并解决这些问题是Java程序员进阶的必备要求。本文将对一些常用的JVM性能调优监控工具进行介绍,希望能起抛砖引玉之用。本文参考了网上很多资料,难以一一列举,在此对这些资料的作者表示感谢!关于JVM性能调优相关的资料,请参考文末。 A、 jps(Java Virtual Machine Process Status Tool) jps主要用来输出JVM中运行的进程状态信息。语法格式如下: 1 jps [options] [hostid] 如果不指定hostid就默认为当前主机或服务器。 命令行参数选项说明如下: 1 2 3 4 -q 不输出类名、Jar名和传入main方法的参数 -m 输出传入main方法的参数 -l

[JVM教程与调优] 什么是JVM运行时参数?

空扰寡人 提交于 2020-04-24 17:52:14
我们接着上一章节 [JVM教程与调优] JVM都有哪些参数类型? 的内容继续讲解,这章我们来介绍一下:如何查看JVM运行时参数。这一点十分重要,因为我们在进行JVM参数调优的时候,我们首先得知道目前系统运行的值是什么,然后相应的根据相关参数进行调优。 1.-XX:+PrintFlagsInitial(查看初始值) 2.-XX:+PrinFlagsFinal(查看最终值) 3.-XX:+UnlockExperimentalVMOptions(解锁实验参数) 4.-XX:+UnlockDiagnosticVMOptions(解锁诊断参数) 5.-XX:+PrintCommandLineFlags(打印命令行参数) PrinFlagsFinal bool类型 属性名:UseG1GC 值:false 因此可以看出,并没有使用G1GC。 InitialHeapSize := 130023424 表示初始堆的值大小。 注意: =表示默认值 :=被用户或者JVM修改后的值 演示一下 可以看到有非常多的参数。有兴趣的小伙伴可以自己试试。 那么刚才我们看到的参数是哪个进程的呢? 答案是:通过执行 java -XX:+PrinFlagsFinal -version 这个命令时的进程参数值。 如果我们要查看一个在运行时的JVM参数值,那么如何查看呢?这就是我们后面讲到的 jinfo ,在此之前

常见的监控JVM的几个Linux命令和使用

心已入冬 提交于 2020-04-24 14:07:05
jps [root@xxx bin]# jps -l 2007 bash: jps: command not found [root@xxx bin]# /opt/jdk1.8.0_181/bin/jps -q 116471 RMI Registry not available at 116471:1099 Exception creating connection to: 116471; nested exception is: java.net.SocketException: Invalid argument or cannot assign requested address 一、监控管理工具 以下三个命令常用于监视JVM虚拟机性能及资源消耗情况: 1、jps-Java Virtual Machine Process Status Tool 使用说明: 该命令用于列出目标系统上正在运行的虚拟机进程(每个java程序会独占一个java虚拟机实例)。所列信息包括进程ID及虚拟机执行主类名称,对于非root账户,只能显示当前用户启动的虚拟机进程。值得注意的是,java程序启动后,默认会在/tmp/hsperfdata_${user_name}目录下以该进程ID为文件名的文件,并将jvm运行相关信息存储其中,其中user_name是当前用户名。出现无法查看时,可能是磁盘读写

【Bug处理系列】CPU虚高故障分析

时光总嘲笑我的痴心妄想 提交于 2020-04-23 07:30:26
总结步骤: 1,使用命令top -p <pid> ,显示你的java进程的内存情况,pid是你的java进程号,比如123 2,按H,获取每个线程的内存情况 3,找到内存和cpu占用最高的线程pid,比如15248 4,执行 printf 0x%x 15248 得到 0x3b90 ,此为线程id的十六进制 5,执行 jstack <pid进程>|grep -A 10 <转换的16进制线程Id>,得到线程堆栈信息中3b90这个线程所在行的后面10行 6,查看对应的堆栈信息找出可能存在问题的代码。 查看线程内存: top -H -p pid ,另一种方法通过pstree pid查到pid下所有的thread 然后top查看,按下H找到对应的线程即可。 1 故障现象 这天上午,有同事反映公司后台管理系统运行缓慢,运维同事检查发现cpu占用过高,重启服务器后故障消失。 这天下午,有同事也反映后台系统的某模块系统,运行缓慢,多次重启后故障仍然存在,使用top命令查看服务器的情况,发现cpu占用率接近100%。 2 cpu问题定位 定位问题进程 使用了top指令查看资源占用情况,发现PID为11705的进程消耗了大量的CPU资源,达到了780.4 定位问题线程 使用 ps -mp 11705 -o THREAD,tid,time 指令把该11705进程的thread,tid,time给列出来,

JVM内存设置多大合适?Xmx和Xmn如何设置?

自闭症网瘾萝莉.ら 提交于 2020-04-23 04:52:04
JVM内存设置多大合适?Xmx和Xmn如何设置? 问题: 新上线一个java服务,或者是RPC或者是WEB站点, 内存的设置该怎么设置呢?设置成多大比较合适,既不浪费内存,又不影响性能呢? 分析: 依据的原则是根据Java Performance里面的推荐公式来进行设置。 296d1509689688.png 具体来讲: Java整个堆大小设置,Xmx 和 Xms设置为老年代存活对象的3-4倍,即FullGC之后的老年代内存占用的3-4倍 永久代 PermSize和MaxPermSize设置为老年代存活对象的1.2-1.5倍。 年轻代Xmn的设置为老年代存活对象的1-1.5倍。 老年代的内存大小设置为老年代存活对象的2-3倍。 BTW: 1、Sun官方建议年轻代的大小为整个堆的3/8左右, 所以按照上述设置的方式,基本符合Sun的建议。 2、堆大小=年轻代大小+年老代大小, 即xmx=xmn+老年代大小 。 Permsize不影响堆大小。 3、为什么要按照上面的来进行设置呢? 没有具体的说明,但应该是根据多种调优之后得出的一个结论。 如何确认老年代存活对象大小? 方式1(推荐/比较稳妥): JVM参数中添加GC日志,GC日志中会记录每次FullGC之后各代的内存大小,观察老年代GC之后的空间大小。可观察一段时间内(比如2天)的FullGC之后的内存情况

Java进程故障排查(CPU资源占用高,接口响应超时,功能接口停滞等)

痴心易碎 提交于 2020-04-22 04:00:54
故障分析 # 导致系统不可用情况(频率较大): 1)代码中某个位置读取数据量较大,导致系统内存耗尽,进而出现Full GC次数过多,系统缓慢; 2)代码中有比较消耗CPU的操作,导致CPU过高,系统运行缓慢; # 导致某功能运行缓慢(不至于导致系统不可用): 3)代码某个位置有阻塞性的操作,导致调用整体比较耗时,但出现比较随机; 4)某线程由于某种原因进入WAITTING状态,此时该功能整体不可用,但无法复现; 5)由于锁使用不当,导致多个线程进入死锁状态,导致系统整体比较缓慢。 # 说明 对于后三种情况而言,是具有一定阻塞性操作,CPU和系统内存使用情况都不高,但功能却很慢,所以通过查看资源使用情况是无法查看出具体问题的! 应急处理 ### 对于线上系统突然产生的运行缓慢问题,如果导致线上系统不可用。 首先要做的是导出jstack和内存信息,重启服务器,尽快保证系统的高可用 。 ### 导出jstack信息 为避免重复赘述,此操作将在后面的" 排查步骤 "章节中体现! ### 导出内存堆栈信息 # 查看要导出的Java项目的pid # jps -l or # ps -ef |grep java # 导出内存堆栈信息 jmap -dump:live,format=b,file=heap8 <pid> # heap8是自定义的文件名 # 运行导出的堆栈文件 # ls heap8 #

《深入理解 Java 虚拟机》笔记整理

不羁的心 提交于 2020-04-18 14:51:40
《深入理解 Java 虚拟机》笔记整理 正文 一、Java 内存区域与内存溢出异常 1、运行时数据区域 程序计数器:当前线程所执行的字节码的行号指示器。线程私有。 Java 虚拟机栈:Java 方法执行的内存模型。线程私有。 本地方法栈:Native 方法执行的内存模型。线程私有。 Java 堆:存放对象实例。分为新生代(Eden 空间、From Survivor 空间、To Survivor 空间)和老年代。线程共享。 方法区:存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。也称为“永久代”。线程共享。 运行时常量池:方法区的一部分,用于存放编译期生成的各种字面量和符号引用。 线程共享。 直接内存。 2、对象的创建 类加载检查 -> 分配内存 -> 初始化零值 -> 设置对象头 -> 执行 init 方法。 类加载检查:检查 new 指令的参数能否在常量池中定位到一个类的符号引用,以及这个符号引用代表的类是否已被加载、解析和初始化过。 分配内存:把一块确定大小的内存从 Java 堆中划分出来。 初始化零值:将分配到的内存空间初始化为零值(不包括对象头)。 设置对象头:虚拟机需要对对象进行必要的设置,这些信息存放在对象的对象头中。 执行 init 方法:把对象按照程序员的意愿进行初始化。 3、对象的内存布局 对象头: Mark Word

《深入理解 Java 虚拟机》笔记整理

风格不统一 提交于 2020-04-17 10:17:16
【推荐阅读】微服务还能火多久?>>> 正文 一、Java 内存区域与内存溢出异常 1、运行时数据区域 程序计数器 :当前线程所执行的字节码的行号指示器。线程私有。 Java 虚拟机栈 :Java 方法执行的内存模型。线程私有。 本地方法栈 :Native 方法执行的内存模型。线程私有。 Java 堆 :存放对象实例。分为新生代(Eden 空间、From Survivor 空间、To Survivor 空间)和老年代。线程共享。 方法区 :存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。也称为“永久代”。线程共享。 运行时常量池 :方法区的一部分,用于存放编译期生成的各种字面量和符号引用。 线程共享。 直接内存 。 2、对象的创建 类加载检查 -> 分配内存 -> 初始化零值 -> 设置对象头 -> 执行 init 方法。 类加载检查 :检查 new 指令的参数能否在常量池中定位到一个类的符号引用,以及这个符号引用代表的类是否已被加载、解析和初始化过。 分配内存 :把一块确定大小的内存从 Java 堆中划分出来。 初始化零值 :将分配到的内存空间初始化为零值(不包括对象头)。 设置对象头 :虚拟机需要对对象进行必要的设置,这些信息存放在对象的对象头中。 执行 init 方法 :把对象按照程序员的意愿进行初始化。 3、对象的内存布局 对象头 : Mark

一次频繁Full GC的排查过程

假如想象 提交于 2020-04-17 03:26:10
【推荐阅读】微服务还能火多久?>>> 问题描述 最近公司的线上监控系统给我推送了一些kafka lag持续增长的消息,我上生产环境去看了相应的consumer的情况,发现几台机器虽然还在处理消息,但是速度明显慢了很多。 问题猜测与验证 我猜测是JVM频繁做Full GC,导致进程也跟着频繁卡顿,处理消息的速度自然就慢了。为了验证这个想法,先用jstat看看内存使用情况: jstat -gcutil 1 1000 #1是进程号 结果如我所料,几乎1秒钟就要做一次FGC,能安安静静的做个正常的consumer才有鬼了。 赶紧留了一台consumer拿来做分析,把别的几台consumer都重启。不管怎样,先恢复消费能力再说! 内存泄露root cause排查 1秒一次FGC,那肯定是发生内存泄露了。 二话不说,把堆dump下来先! jmap -F -dump:format=b,file=heapDump 1 #1是进程号 生成的heapDump文件有将近2个G的大小,这么大个文件,为了不影响生产环境的机器,还是scp到本地进行分析吧! jhat了一下,直接卡在那里不动了。没办法,祭出VisualVM来帮忙。导入文件之后,发现有一大堆HashMap的Node在那占着: 然而并不知道这是个啥,点进去看看内容,发现有一大堆node的key类型是X509CertImpl: 这时候我意识到

面试之Java虚拟机专题

若如初见. 提交于 2020-04-10 10:00:07
说下对象的创建方法?对象的内存布局?对象的访问定位? 四种不同的方法创建对象 1、用new语句创建对象,这是最常用的创建对象的方式; 2、调用对象的clone方法。   MyObject obj =new MyObject();   MyObject objs= obj.clone(); 使用clone方法克隆一个对象的步骤:   1)被克隆的类要实现Cloneable接口;   2)被克隆的类要重写clone方法; 1 class Obj implements Cloneable{ 2 private Date birth = new Date(); 3 public Date getBirth(){ 4 return birth; 5 } 6 public void setBirth(){ 7 this .birth= birth; 8 } 9 public void changeDate(){ 10 this .birth.setMonth(4 ); 11 } 12 public Object clone(){ 13 Obj o = null ; // o指向了复制后的新对象 14 try { 15 o=(Obj) super .clone(); // 实现浅复制 16 } catch (CloneNotSupportedException e){ 17 e