一、概述

1、导致出现性能问题的因素

1、线程控制
2、磁盘读写
3、数据库访问
4、网络I/O
5、垃圾收集

2、为什么需要调优

1、防止出现OOM《关于OOM可以参考》
2、解决OOM
3、减少Full GC出现的频率

3、性能优化的步骤

1、性能监控
2、性能分析
3、性能调优:
4、性能指标《可以参考垃圾回收的GC的性能指标评估》

4、简单命令行工具

在jdk安装的bin目录中,有一系列的辅助工具,用来获取目标JVM不同方面、不同层次的信息,帮助开发人员很好地解决Java应用程序的一些问题。

二、jps:查看正在运行的Java程序

1、jps介绍

1、jps(Java Process Status):显示指定系统内所有的HotSpot虚拟机进程(查看虚拟机进程信息),可用于查询正在运行的虚拟机进程。
2、对于本地虚拟机进程来说,进程的本地虚拟机ID与操作系统的进程ID是一致的,也是唯一的。

2、jps语法参数

1、基本语法:jsp [options] [hostid]
2、options参数说明

3、hostid参数说明

三、jstat:查看JVM统计信息

1、jstat介绍

1、jstat(JVM Statistics Monitoring Tool):用于监听虚拟机各种运行状态信息的命令行工具,可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。
2、在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的首选工具,常用于检测垃圾回收问题以及内存泄漏问题。官方文档

2、jstat语法参数

1、基本语法:jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
2、vmid:是进程id号,也就是通过jps命令查到的Java程序id
3、option:是可选参数
4、interval:用于指定输出统计数据的周期,单位为毫秒。即:查询间隔
  • 该命令会一直运行,除非手动停止,或者程序出现异常才会停止

5、count:用于指定输出统计数据的总次数

6、-t:在输出信息前加上一个Timestamp列,显示程序的运行时间(单位:秒)

7、-h:可以在周期性数据输出时,输出多少行数据后输出一个表头信息

3、option参数详细说明

1、类装载相关的:
  • -class:显示ClassLoader的相关信息:类的装载、卸载数量、总空间、类装载所消耗的时间等
2、垃圾回收相关的:
3、JIT相关的:

4、垃圾回收相关参数使用举例

/*** @Date: 2022/1/16* JVM启动参数:-Xms60m -Xmx60m -XX:SurvivorRatio=8*/
public class GCTest {public static void main(String[] args) {ArrayList<byte[]> list = new ArrayList<>();for (int i = 0; i < 1000; i++) {//每次创建100kb大小的数组byte [] bytes = new byte[1024 * 100];list.add(bytes);try {Thread.sleep(120);} catch (InterruptedException e) {e.printStackTrace();}}}
}
1、-gc参数使用举例

表头列含义说明:
2、-gcutil参数使用举例:在堆溢出之前会发生FULL GC

表头列含义说明:
3、-gccause参数使用举例

表头参数说明:

5、补充说明

1、-t参数补充说明

2、jstat还可以用来判断是否出现内存泄漏

四、jinfo:实时查看和修改JVM配置参数

1、jinfo介绍

1、jinfo(Configuration Info for Java):用于查看虚拟机配置参数信息,也可以调整虚拟机的配置参数(立即生效)。
2、在很多情况下,Java应用程序不会指定所有的Java虚拟机参数。而此时,开发人员可能不知道某一个具体的Java虚拟机参数的默认值,此时可以通过jinfo命令可以很方便的查看Java虚拟机参数的当前值。

2、jinfo语法参数

1、基本语法:jinfo [options] pid
2、options参数说明:
参数名 说明
no option 不带任何可选参数,直接jinfo pid,输出全部的参数和系统属性
-flag name 输出对应name的参数
-flag +name 开启name对应的参数,只有被标记为manageable的参数才可以被动态修改
-flag -name 关闭name对应的参数,只有被标记为manageable的参数才可以被动态修改
-flag name=value 设定name对应的参数
-flags 输出全部的参数
-sysprops 输出系统参数
3、注意:对参数进行修改的时候,会立即生效,但是并非所有的参数都支持动态修改。参数只有被标记为manageable的可以被实时修改

3、option相关参数使用举例

1、-sysprops:可以查看由System.getProperties()取得的参数

2、-flags:查看赋过值的一些参数

3、-flag name:查看具体参数的值,比如查看使用的垃圾收集器

4、-flag [+-]name 或 -flag name=value:动态的开启或者关闭某个参数,或者给数值类型的参数设定值

4、补充说明

1、java -XX:+PrintFlagsInitial:查看所有JVM参数启动的初始值
2、java -XX:+PrintFlagsFinal:查看所有JVM参数的最终值
3、java -XX:+PrintCommandLineFlags:查看哪些已经被用户或者JVM设置过的详细的XX参数的名称和值

五、jmap:导出内存映像文件与内存使用情况

1、jmap介绍

1、jmap(JVM Memory Map):作用一方面是获取dump文件(堆转储快照文件,二进制文件),它还可以获取目标Java进程的内存相关信息,包括Java堆各区域的使用情况、堆中对象的统计信息、类加载信息等。

2、jmap语法参数

1、基本语法有三种情况:
2、option参数说明:
参数名 说明
-dump 生成dump文件
-finalizerinfo 显示在F-Queue中等待的Finalizer线程执行finalize方法的对象(linux中有效)
-heap 输出整个堆空间的详细信息,包括GC的使用、堆配置信息,以及内存的使用信息等
-histo 输出堆空间中对象的统计信息,包括类、实例数量和合计容量
-permstat 以ClassLoader为统计口径输出永久代的内存状态信息(linux中有效)
-F 当虚拟机进程对-dump选项没有任何响应时,强制执行生成dump文件(linux中有效)
**`-h -help`**
-J <flag> 传递参数给jmap启动的JVM,例如-J -Xms60m
3、executable <core>:代表可执行的代码,比如使用 > 文件名称来指定生成的dump文件存放位置
4、[server_id@]<···>:是为远程连接准备的

3、option重要参数的详细说明

1、-dump:生成Java堆转储快照dump文件,它还有如下几个可选参数:
2、-heap:输出整个堆空间的详细信息,包括GC的使用、堆配置信息,以及内存的使用信息等
3、-histo:输出堆空间中对象的统计信息,包括类、实例数量和合计容量,还有一个可选参数:
  • -histo:live:只统计堆中的存活对象

4、关于Heap Dump介绍

1、Heap Dump又叫做堆存储文件,指一个Java进程在某个时间点的内存快照。Heap Dump在触发内存快照的时候会保存此刻的信息如下:
2、说明
  • 通常在写Heap Dump文件前会触发一次Full GC,所以Heap Dump文件里保存的都是FullGC后留下的对象信息。
  • 生成dump文件比较耗时
3、注意:

5、手动方式导出内存映像文件

1、手动方式导出内存映像文件:
2、说明
/*** @Date: 2022/1/19* jmap命令测试* JVM启动参数:-Xms60m -Xmx60m -XX:SurvivorRatio=8*/
public class JMap {public static void main(String[] args) {ArrayList<byte[]> list = new ArrayList<>();for (int i = 0; i < 1000; i++) {//每次创建100kb大小的数组byte [] bytes = new byte[1024 * 100];list.add(bytes);try {Thread.sleep(120);} catch (InterruptedException e) {e.printStackTrace();}}}
}
1、运行程序,打开cmd

6、自动方式导出内存映像文件

1、当程序发生OOM退出系统时,一些瞬间信息都会随着程序的终止而消失,而重现OOM问题往往比较困难或者耗时,自动导出dump文件就很重要了。
2、设置JVM启动参数自动生成内存映像文件:
3、设置JVM启动参数

7、显示堆内存相关信息

1、jmap -heap pid只是时间点上的堆信息,而jstat可以添加参数,可以指定时间动态观察数据改变情况,而图形化界面工具(例如:jvisualVM)可以直观明了的用图表的方式动态展示出相关信息。

2、jmap -histo pid输出当前时刻内存中的堆中对象的同级信息,包括类、实例数量和合计容量

3、缺点:不能连续进行监控

8、补充说明

1、由于jmap将访问堆中的所有对象,为了保证在此过程中不被应用程序干扰,jmap需要借助安全点机制,让所有线程停留在不改变堆中数据的状态。也就是说,由jmap导出的堆快照必订是安全点位置的,可能会导致基于该堆快照的分析结果存在偏差。
2、假设在编译生成的机器码中,某些对象的生命周期在两个安全点之间,那么:live参数将无法探知到这些对象。
3、如果某一个线程长时间无法跑到安全点,jmap会一直等待下去。
4、与jstat不同是垃圾回收器会主动将jstat所需要的摘要数据保存至固定位置之中,jstat直接读取即可。

六、jhat:JDK自带堆分析工具

1、jhat介绍

1、jhat命令在JDK9及其之后就被移除了,官方建议使用jvisualVM代替jhat,所以简单了解即可
2、jhat(Java Heap Analysis Tool):是Sun JDK提供的,与jmap命令搭配使用,用于分析jmap生成的dump文件(堆转储快照)。jhat内置了一个微型的HTTP/HTML服务器,生成dump文件的分析结果后,可以在浏览器中查看分析结果。
3、使用jhat命令,就启动了一个http服务,生成之后会返回一个端口号,通过http://localhost:端口号即可访问

2、jhat语法参数

1、基本语法:jhat [option] dumpFile
2、dumpFile:表示dump文件的地址及名称
3、option参数说明:
参数名 说明
**`-stack false true`**
**`-refs false true`**
-port <port> 设置jhat的HTTP Server的端口号,默认7000
-exclude <file> 执行对象查询时需要排除的数据成员
-baseline <file> 指定一个基准堆转储
-debug <int> 设置debug级别,可选0,1,2三个级别
-version 启动后显示版本就退出
-J <flag> 传入启动参数,如:-J -Xms60m

3、使用示例

1、对之前导出的dump文件进行分析

2、浏览器访问http://localhost:7000查看分析结果
  • 分析结果默认以包为单位进行分组显示,分析内存泄漏问题主要会使用到其中的“Heap Histogram”(与jmap-histo功能一样)与OQL页签的功能,前者可以找到内存中总容量最大的对象,后 者是标准的对象查询语言,使用类似SQL的语法对内存中的对象进行查询统计。

七、jstack:打印JVM中线程快照

1、jstack介绍

1、jstack(JVM Stack Trace):用于生成虚拟机指定进程当前时刻的线程快照(虚拟机堆栈跟踪)。线程快照就是当前虚拟机内每一条线程正在执行的的方法堆栈的集合。
2、生成线程快照的目的通常是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因。线程出现停顿时通过jstack来查看各个线程的调用堆栈, 就可以获知没有响应的线程到底在后台做些什么事情,或者等待着什么资源
3、在线程dump文件中,要留意下面几种状态

2、jstack语法参数

1、基本语法:jstack [option] pid
2、option参数说明:
参数名 说明
-F 当正常输出的请求不被响应时,强制输出线程堆栈
-l 除堆栈外,显示关于锁的附加信息
-m 如果调用到本地方法的话,可以显示C/C++的堆栈

3、使用示例

/*** @Date: 2022/1/20* 演示线程死锁* 死锁:是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的* 一种阻塞的现象,若无外力作用,它们都将无法推进下去。(相互不释放资源从而相互等待)*/
public class DeadLock {public static void main(String[] args) {Object A = new Object();Object B = new Object();Thread t1 = new Thread(()->{synchronized (A) {System.out.println(new Date() + "【"+ Thread.currentThread().getName() + "】 - Lock A");try {sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (B) {System.out.println(new Date() + "【"+ Thread.currentThread().getName() + "】 - Lock B");System.out.println(new Date() + "【"+ Thread.currentThread().getName() + "】 - 操作...");}}},"t1");Thread t2 = new Thread(()->{synchronized (B) {System.out.println(new Date() + "【"+ Thread.currentThread().getName() + "】 - Lock B");try {sleep(500);} catch (InterruptedException e) {e.printStackTrace();}synchronized (A) {System.out.println(new Date() + "【"+ Thread.currentThread().getName() + "】 - Lock A");System.out.println(new Date() + "【"+ Thread.currentThread().getName() + "】 - 操作...");}}},"t2");t1.start();t2.start();}
}
1、运行程序,打开cmd,首先通过jps获取到当前运行程序的进程id,再通过jstack命令查看线程堆栈结果

2、查看部分结果

3、接着往下看分析结果

/*** @Date: 2022/1/20* 演示线程TIMED_WAITING*/
public class ThreadSleep {public static void main(String[] args) {System.out.println(">>>开始");try {//线程休眠10分钟Thread.sleep(1000 * 60 * 10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(">>>结束");}
}
1、运行程序之后,通过jstack命令查看线程堆栈结果

/*** @Date: 2022/1/21* 演示线程同步*/
public class ThreadSyn {public static void main(String[] args) {Number number = new Number();Thread thread1 = new Thread(number);Thread thread2 = new Thread(number);thread1.setName("线程1");thread2.setName("线程2");thread1.start();thread2.start();}
}class Number implements Runnable {private int number = 1;@Overridepublic void run() {while (true) {synchronized (this) {if (number <= 100) {try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ":" + number);number++;} else {break;}}}}
}
1、运行程序之后,通过jstack命令查看线程堆栈结果

4、补充:通过代码方式监控线程

1、从JDK 5起,java.lang.Thread类新增了一个getAllStackTraces()方法用于获取虚拟机中所有线程的StackTraceElement对象。使用这个方法可以通过简单的几行代码完成jstack的大部分功能
/*** @Date: 2022/1/21* 通过代码方式查看线程状况*/
public class AllStackTrace {public static void main(String[] args) {//获取虚拟机中所有线程的StackTraceElement对象Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();for (Map.Entry<Thread, StackTraceElement[]> threadEntry : allStackTraces.entrySet()) {Thread thread = threadEntry.getKey();StackTraceElement[] value = threadEntry.getValue();System.out.println("Thread name is 【" + thread.getName() + "】");for (StackTraceElement element : value) {System.out.println("\t" + element.toString());}}}
}

5、jstack管理远程进程

1、需要在远程程序的启动参数中增加如下配置:

八、jcmd:多功能命令行

1、jcmd介绍

1、在JDK1.7之后,新增了一个命令行工具jcmd。它是一个多功能工具,可以用来实现除了jstat之外的所有命令的功能,比如:用它来导出堆、内存使用、查看Java进程、导出线程信息、执行GC、JVM运行时间等。
2、jcmd拥有jmap的大部分功能,并且在Oracle的官网上也推荐使用jcmd命令替代jmap命令。

2、jcmd语法参数

1、jcmd -l:列出所有的JVM进程
2、jcmd pid help:针对指定的进程,列出支持的所有命令
3、jcmd pid 具体命令:显示指定进程的指令命令的数据
4、具体命令有哪些的获取方式:通过jcmd pid help查询出来

二十、JVM命令行监控工具相关推荐

  1. JVM命令行监控工具之jhat(Java Heap Analysis Tool)

    jhat简介 jhat命令与jmap命令搭配使用,用于分析jmap生成的heap dump文件(堆转储快照).jhat内置了一个微型的HTTP/HTML服务器,对生成的dump文件分析后,可以在浏览器 ...

  2. JVM命令行监控工具之jmap(JVM Memory Map)

    jmap简介 jmap(JVM Memory Map)一方面可以获取dump文件(堆转储快照文件,二进制文件),它还可以获取目标Java进程的内存相关信息,包括Java堆各区域的使用情况.堆中对象的统 ...

  3. java内存溢出排查jstack_Java命令行监控工具(jmap,jstack,jstat,jinfo,jps)

    项目部署上线之后,线上项目是不能轻易修改的,定位问题的难度也会变大.因此监控是非常重要的一个环节,有了监控,我们才能更好的定位系统中的问题,从而排查.监控的工具有很多种, 但是java自带的命令行监控 ...

  4. Java内存泄露和内存溢出、JVM命令行工具、.JDK可视化工具、Java Class文件

    1.Java内存泄露和内存溢出对比 1.1 Java 内存泄露 内存泄露是指一个不再被程序使用的对象或变量还在内存中占用空间. 1.1.1判断内存空间是否符合垃圾回收的标准 在Java语言中,判断一个 ...

  5. java jamp cmd,Java命令行监控工具jmap,jstack...

    原标题:Java命令行监控工具jmap,jstack... Java命令行监控工具(jmap,jstack,jstat,jinfo,jps) 项目部署上线之后,线上项目是不能轻易修改的,定位问题的难度 ...

  6. Homebrew进阶使用教程(二)-用一个命令行天气客户端构建自己的仓库

    [homebrew 系列文章] HomeBrew常规使用教程 Homebrew进阶使用教程(一) Homebrew进阶使用教程(二)-用一个命令行天气客户端构建自己的仓库 Homebrew进阶使用教程 ...

  7. NASM学习(二)——从命令行获取参数

    NASM学习(二)--从命令行获取参数 学习汇编的目的是增强自己对硬件体系的熟悉与编译.链接等等阶段的熟悉 上文我们已经学会了怎么使用NASM来打印HELLO,WORLD了,总结一下,主要是使用系统调 ...

  8. 第五十二课、命令行参数的应用------------------狄泰软件学院

    一.主窗口的状态参数 1.主窗口的状态参数 (1).应用程序必须保存和恢复主窗口的状态参数(位置.大小等) 2.应用程序退出的过程 (1).收到关闭事件 (2).执行关闭事件处理函数 (3).主窗口从 ...

  9. pytest十二:cmd命令行参数

    命令行参数是根据命令行选项将不同的值传递给测试函数,比如平常在 cmd 执行"pytest -html=report.html",这里面的"-html=report.ht ...

最新文章

  1. 人人都能学会的python编程教程15:高级特性2
  2. (010) java后台开发之String字符串操作
  3. 数据结构和算法之稀疏数组
  4. 全国计算机考试光盘,全国计算机一级模拟考试题(光盘).doc
  5. 学习 shell脚本之前的基础知识
  6. JS高级——函数执行、作用域链内存结构图
  7. php strchr 截断,PHP strchr() 函数
  8. linux ssh 插件,玩转VSCode插件之Remote-SSH的使用情况
  9. 如何只保留1000条数据mysql_php实现只保留mysql中最新1000条记录
  10. drawpolygon收尾不连接_门窗施工全流程,80%的设计师都不了解!
  11. 倒数58天 -- 分治法 -- 使用循环求方程的一个解
  12. gdb 查看是否 栈溢出_ASLR、DEP与栈保护(HFUT-ZRB#x27;s Task)
  13. idea中刷新maven依赖,总是拉不下来
  14. 分离开发中的laravel
  15. html前端毕业设计项目,web前端毕业设计论文..doc
  16. 图的拓补排序(TopologicalSort)算法在邻接表与邻接矩阵结构下实现
  17. 虚拟机调整C盘分区大小的取巧方法
  18. 【Pandas总结】第八节 Pandas 合并数据集_pd.merge()
  19. 深圳市专精特新企业申报流程及奖励政策重点介绍,补贴20-50万
  20. C语言 共享内存实现进程间通信

热门文章

  1. 【Alpha】Scrum Meeting 5
  2. SQLyog数据库列表(对象浏览器)字体大小设置方法,不是普通字体大小设置
  3. 超硬核!MySQL优化从执行计划开始(explain超详细)
  4. 实时操作系统概述(推荐) .
  5. StringUtils java
  6. input如何禁止文本框输入的方法
  7. python人工智能入门零基础_【贾老坏】真·零基础入门人工智能+Python+数学
  8. SMPL模型及源码解读
  9. 【转】HttpClient之 addHeader与setHeader
  10. ORA-00054资源正忙解决方法