LearnJava
  • Summary
    • Introduction
    • MyResume
  • 开发
    • 小程序
      • 小程序开发问题总结
      • 小程序bug
    • 环境搭建
      • Linux搭建git服务器
      • Linux切换JDK版本
      • Mac搭建http服务器
      • Ubuntu搭建C++开发环境
      • ProtoBuffer安装
      • Ubuntu开启Telnet
      • Linux搭建邮件服务器
    • 遇到的问题
      • Mac下eclipse问题
      • Mac下Github问题
      • Markdown解决方案实例
      • Spring问题
  • 编程语言
    • C++
      • C&C++框架汇总
      • C++Primer课后习题记录
      • C++疑问
      • C++与java的异同
      • C++内存模型
      • C++知识点
      • Make和Cmake
    • GO
      • Go语言简介
      • Go语言知识点
    • XML
      • XML知识点
  • 技术学习
    • JavaIO
      • AIO通信
      • IO和NIO
      • 阻塞式IO通信
      • 非阻塞式IO通信
    • 计算机网络
      • CDN
      • HTTPS协议入门
      • HTTP_POST请求的数据格式
      • HTTP错误码和出现场景
      • HTTP协议入门
      • TCP/IP协议入门
      • Wireshark抓包
      • 域名解析过程
    • 计算机原理
      • 整型计算
      • GPU
      • Swap内存
    • 架构学习
      • 分布式锁
      • 分布式系统的CAP理论
      • IaaS,PaaS,SaaS的区别
      • Web框架
      • 康威定律
      • 秒杀系统设计
      • 数据异构
      • 微服务架构入门
      • 协程
      • MQ推拉模式对比
      • UML图
      • 缓存穿透击穿和雪崩
    • 前端学习
      • 安装使用VUE
      • 搭建VUE项目
    • 大数据
      • Hadoop之HBASE
      • Hadoop之HDFS
      • Hadoop之MapReduce
      • Hadoop简介
    • 数据结构
      • 二叉树
      • 图
      • 跳表
      • Bitmap
    • 算法
      • 排序算法
        • 插入排序
        • 归并排序
        • 计数排序
        • 快速排序
        • 冒泡排序
        • 选择排序
      • Hash算法
      • MD5介绍
      • 一致性Hash算法
      • 数字全排列
      • MD5介绍
      • 储水量
      • 最大子序列
    • Java多线程
      • AQS原理
      • AtomicInteger原理
      • Condition
      • Fork/Join框架
      • happens-before
      • Java锁优化
      • Java线程池
      • Java中的阻塞队列
      • Java实现线程的三种方式
      • Lock
      • Lock的种类
      • ThreadLocal
      • 线程状态及其转换
    • Java设计模式
      • Builder模式
      • 代理模式
      • 工厂和抽象工厂模式
      • 观察者模式
      • 设计模式概述
      • 职责链模式
      • 装饰者模式
      • Java实现单例的5种方式
    • Java学习
      • Java拓展学习
        • JavaSPI
      • Java序列化
      • Java异常
      • Java注解
      • 学习UML图
      • Java的Lambda表达式
      • Java集合之ArrayList
      • Java集合之HashMap
      • Java集合之LinkedList
      • List⤅&Set的操作和遍历
      • JavaP反编译命令
      • Servlet学习
    • JVM学习
      • 分层编译
      • Java进程内存占用
      • JVM参数
      • JVM常用工具
      • JVM的内存模型
      • 垃圾回收机制
      • 看懂gc日志
      • 类加载机制和双亲委派模型
      • 类的反射
      • 自己动手编译OPENJDK
      • ASM字节码增强技术
      • CodeCache
      • GC耗时案例
      • JVM性能调优
    • Linux学习
      • gdb调试定位
      • Linux常用命令
      • Linux工具
      • Linux进程通信的方式
      • Linux文件系统结构
      • Linux系统知识点
      • Linux小技巧
      • Shell学习
      • Vim常用命令
    • Java设计模式
      • 设计模式概述
      • 代理模式
      • 装饰者模式
    • Mysql
      • InnoDB介绍
      • Mac_mysql问题
      • mysql之group_concat函数
      • mysql事务
      • Mysql优化
      • Mysql实用命令
      • mysql慢查询
      • mysql文件
      • mysql视图
      • mysql锁
      • mysql索引
      • mysql约束
      • 存储过程和触发器
      • mysql常用语法
    • Spring
      • SpringCloud
        • 搭建Jenkins自动部署
        • SpringCloud介绍
        • SpringCloudBus
        • SpringCloudConfig
        • SpringCloudEureka
        • SpringCloudFeign
        • SpringCloudHystrix
        • SpringCloudRibbon
        • SpringCloudSleuth
        • SpringCloudStream
        • SpringCloudZuul
      • FactoryBean理解
      • MyBatis入门介绍
      • rose框架学习
      • SpringMVC的启动流程
      • SpringBean的生命周期
      • SpringBoot入门
      • Spring入门AOP和IOC
      • SpringMVC入门笔记
      • SpringMVC集成Log4j2
      • web.xml详解
    • web中间件学习
      • Redis
        • Redis入门
        • Redis持久化
        • Redis的数据类型
        • Redis特性
      • Gremlin入门
      • Elasticsearch安装使用
      • HugeGraph入门
      • jetty介绍
      • Kafka介绍使用
      • Maven安装配置
      • Netty介绍使用
      • Netty的编解码
      • Maven的pom介绍
      • Nginx介绍
      • Nginx配置详解
      • ProtocolBuffers学习笔记
      • Resin学习
      • RESTful入门
      • RocketMQ入门
      • RPC入门
      • Thrift介绍
      • Tomcat常用配置
      • Tomcat学习
      • Tomcat实现
      • zookeeper入门
      • Zookerper选举原理
  • 文档读后感
    • 除了写代码你还会干什么
  • 效率提升
    • Java诊断工具Arthas
    • Mac下安装多版本java
    • Mac下显示git分支
    • Mac中Clion快捷键
    • Mac中Eclipse快捷键
    • MacShell常用快捷键
    • PlantUML入门
    • Windows与Linux服务器传文件
    • Sublime技巧
    • 搜索引擎检索技巧
  • 总结
    • 2017工作总结
Powered by GitBook
On this page
  • 一、jps
  • 二、jstat
  • 三、jinfo
  • 四、jstack
  • 五、jmap
  • 六、jhat
  • 七、可视化工具Java VisualVM
  • 7.1 线程Dump

Was this helpful?

  1. 技术学习
  2. JVM学习

JVM常用工具

jdk给我们提供了很多有用的小工具,就在bin目录下,本质上是对lib/tools.jar中接口的一层封装,下面介绍一下常用的几个工具:

  • jps:列出正在运行的虚拟机进程

  • jstat:用于监视虚拟机各种运行状态信息

  • jinfo:实时查看和调整虚拟机各项参数

  • jstack:java堆栈跟踪工具

  • jmap:生成heap dump文件

JVM常用工具:Jcosole、Visual VM、Jprofiler、MAT。

一、jps

使用jps可以列出所有的虚拟机进程,这个也是使用频率最高的一个命令。常用选项:

选项
作用

-l

输出主类的全名,如果进程执行的是jar包,输出jar路径

-m

输出虚拟机进程启动时传递给主类main()函数的参数

-v

输出虚拟机进程启动时JVM参数

-q

只输出进程id,省略主类名称

小结: 使用这个命令可以查看一个java项目启动的入口,让看一个开源工具变得有迹可循。

二、jstat

jstat是用于监视虚拟机各种运行状态信息的工具,它可以显示本地或者远程虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据,在没有GUI图形界面,只提供了纯文本控制台环境的服务器上,它是运行期定位虚拟机性能问题的首选。

比如需要每250毫秒查询一次进程5190的垃圾收集状况,一共查询20次,那么命令应是:

jstat -gc 5190 250 20

jstat的作用主要是3类:类装载,垃圾收集,运行期编译情况,具体可以参考以下选项:

选项
作用

-class

监视类装载、卸载数量、总空间以及类装载所耗费的时间

-gc

监视java堆情况,包括Eden区,两个survivor区,老年代,永久代等的容量,已用空间,GC时间合计等信息

-gccapacity

与gc类似,但输出主要关注java堆各个区域使用到的最大,最小空间

-gcutil

与gc类似,但输出主要关注j已使用空间占总空间的百分比

-gccause

与-gcutil功能一样,但是会额外输出导致上一次GC产生的原因

-gcnew

监视新生代GC状况

-gcnewcapacity

与gcnew类似,但输出主要关注使用到的最大,最小空间

-gcold

监视老年代GC状况

-gcoldcapacity

与gcold类似,但输出主要关注使用到的最大,最小空间

-gcmetacapacity

-compiler

输出JIT编译器编译过的方法、耗时等信息

-printcompilation

输出已被JIT编译的方法

使用jstat纯文本工具确实不如VisualVM等可视化监视工具直接以图表那样展示方便,但在没有GUI图形界面的系统是一个不错的选择。

三、jinfo

jinfo可以实时查看和调整虚拟机各项参数,使用jps -v可以查看虚拟机启动时指定的参数列表,但如果想看未被显示指定的参数的系统默认值,就可以使用jinfo了。

选项
作用

flags

查看所有的虚拟机默认参数。注意:在运行时可能会遇到Operation not permitted错误,目前还没有找解决办法,可以使用java -XX:+PrintFlagsFinal 同样可以查看虚拟机的全部参数。比如:jinfo -flags 19891

flag

查看单个虚拟机参数,比如:jinfo -flag AdaptiveSizeDecrementScaleFactor 5190。可以使用-flag [+|-] name 或者 -flag name=value修改一部分运行期可写的虚拟机参数值。

sysprops

查看虚拟机System.getProperites()的内容。

四、jstack

jstack命令用于生成虚拟机当前时刻的线程快照。线程快照就是当前虚拟机内每一条线程正在执行的方法栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁,死循环、请求外部资源导致的长时间等待都是导致线程长时间停顿的常见原因。线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做些什么事情,或者等待着什么资源。

命令格式: jstack [option] vmid

选项
作用

-F

当正常输出的请求不被响应时,强制输出线程堆栈

-l

除堆栈外,显示关于锁的附加信息

-m

如果调用到本地方法的话,可以显示C/C++的堆栈

# 示例
jstack 21435
# 查找死循环案例
# 1.使用top找出CPU占用最大的进程{pid}
# 2.使用top -H -p {pid}找出CPU占用最大的线程{tid}
# 3.jstack -l -F {pid} > test.log 打印线程堆栈
# 4.grep {tid} test.log 找出占用CPU最大的线程目前正在运行哪一行
# 5.分析代码

五、jmap

jmap命令用于生成堆转储快照,一般称为heapdump或dump文件。但jmap的作用不仅仅是为了获取dump文件,它还可以查询finalize执行队列、java堆和永久代的详细信息,如空间使用率、当前用的是哪种收集器等。

命令格式: jmap [option] vmid

选项
作用

-dump

生成Java堆转储快照,格式:-dump:[live, ]format=b,file= vmid。live参数说明是否之dump出存活的对象。

-finalizerinfo

显示出F-Queue中等待Finalizer线程执行finalize方法的对象

-heap

显示java堆详细信息,如使用哪种回收器、参数配置、分代状况等。

-histo

显示堆中对象统计信息,包括类、实例数量、合集容量

-clstats

打印类加载器信息

-F

当虚拟机进程对-dump没有响应时,可使用这个参数强制生成dump快照。

实例:

# -dump  生成之后可以使用JVisualVM分析dump文件
jmap -dump:format=b,file=test.log 8188
Heap dump file created
# head
jmap -heap 29766
Attaching to process ID 29766, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.202-b08

using thread-local object allocation.
Garbage-First (G1) GC with 18 thread(s)   # 使用的垃圾收集器是G1

Heap Configuration:  # 堆内存配置情况
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 4294967296 (4096.0MB)
   NewSize                  = 1363144 (1.2999954223632812MB)
   MaxNewSize               = 2576351232 (2457.0MB)
   OldSize                  = 5452592 (5.1999969482421875MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 67108864 (64.0MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 1048576 (1.0MB)

Heap Usage:
G1 Heap:  # 堆内存实际使用情况
   regions  = 4096
   capacity = 4294967296 (4096.0MB)
   used     = 141292960 (134.74746704101562MB)
   free     = 4153674336 (3961.2525329589844MB)
   3.2897330820560455% used
G1 Young Generation:  # 新生代内存使用情况
Eden Space:
   regions  = 55
   capacity = 148897792 (142.0MB)
   used     = 57671680 (55.0MB)
   free     = 91226112 (87.0MB)
   38.732394366197184% used
Survivor Space:
   regions  = 1
   capacity = 1048576 (1.0MB)
   used     = 1048576 (1.0MB)
   free     = 0 (0.0MB)
   100.0% used
   
   G1 Old Generation:  # 老年代内存使用情况
   regions  = 83
   capacity = 106954752 (102.0MB)
   used     = 82572704 (78.74746704101562MB)
   free     = 24382048 (23.252532958984375MB)
   77.20339905981923% used

17541 interned Strings occupying 1547760 bytes.

六、jhat

jhat是虚拟机堆转储快照分析工具,与jmap配合使用,用来分析jmap生成的堆转储快照。jhat内置了一个微型的HTTP/HTML服务器,生成分析结果后可以在浏览器查看。实际应用中一般使用更加完善的分析工具。

$ jhat test.log 
Reading from test.log...
Dump file created Fri Mar 13 12:34:51 CST 2020
Snapshot read, resolving...
Resolving 125137 objects...
Chasing references, expect 25 dots.........................
Eliminating duplicate references.........................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
 
# 通过http://localhost:7000端口访问分析结果

分析结果是以包为单位进行分组显示,分析内存泄漏问题主要会使用其中的heap histogram(与hmap -histo功能一样)和OQL页签的功能,前者可以找到内存中总容量最大的对象,后者是标准的对象查询语言。

七、可视化工具Java VisualVM

VisualVM是目前为止JDK发布的功能最强大的运行监视和故障处理程序。通过插件支持,VisualVM可以做到:

  • 显示虚拟机进程以及进程的配置、环境信息(jps,jinfo)

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

  • dump以及分析堆转储快照(jmap,jhat)

  • 方法级的程序运行性能分析,找出被调用最多、运行时间最长的方法

  • 离线程序快照:收集程序的运行时配置、线程dump、内存dump等信息建立一个快照,可以将快照发送开发者处进行Bug反馈

  • ......

7.1 线程Dump

在指定的进程上右键选择线程dump就会生成一份线程dump,类似下面,里面列出个各个线程的状态,比如从下面的线程dump中可以发现主线程main阻塞在了accept这里。

···
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000005119000 nid=0x1820 in Object.wait() [0x0000000020bbf000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x00000006c2238738> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Unknown Source)
        at java.lang.ref.Reference.tryHandlePending(Unknown Source)
        - locked <0x00000006c2238738> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)

   Locked ownable synchronizers:
        - None

"main" #1 prio=5 os_prio=0 tid=0x0000000005023000 nid=0x3fd4 runnable [0x000000000501e000]
   java.lang.Thread.State: RUNNABLE
        at java.net.DualStackPlainSocketImpl.accept0(Native Method)
        at java.net.DualStackPlainSocketImpl.socketAccept(Unknown Source)
        at java.net.AbstractPlainSocketImpl.accept(Unknown Source)
        at java.net.PlainSocketImpl.accept(Unknown Source)
        - locked <0x00000006c220b568> (a java.net.SocksSocketImpl)
        at java.net.ServerSocket.implAccept(Unknown Source)
        at java.net.ServerSocket.accept(Unknown Source)
        at com.wangjun.io.bio.TimeServer.main(TimeServer.java:30)

   Locked ownable synchronizers:
        - None
...
PreviousJVM参数NextJVM的内存模型

Last updated 2 years ago

Was this helpful?