经过JDK经常使用工具监控Java进程的内存占用状况

Tomcat是一款经常使用的Web容器, 它是运行在 JVM(Java Virtual Machine) 中的一个Java进程.shell

本文以Tomcat为例, 借助一些JDK的工具对Tomcat在运行过程当中的内存占用状况进行监控, 为优化提供数据支撑.服务器

1 JDK 工具的使用

JDK自带的工具位于${JAVA_HOME}/bin/目录下.app

JConsole 能够简单明了地查看到内存的使用状况, 线程的状态, 当前加载的类的总量等.jvm

JVisualVM 能够下载插件(如GC等), 进而查看更丰富的信息. 若是是分析本地的Tomcat的话, 还能够进行内存抽样等, 检查每一个类的使用状况.工具

(1) jps 查看本地运行着的 Java 进程, 及其进程号、进程启动的路径等信息;
优化

(2) jmap 查看垃圾收集策略即 JVM 内存占用状况:.net

jmap -heap pid # 查看垃圾收集策略, 以及堆内存的分配与使用状况.插件

jmap -clstats pid # 查看类加载器的统计数据 —— 此命令调用了sun.jvm.hotspot.runtime.VM.initialize() 方法, 会致使该 pid 对应的 JVM 进程阻塞.线程

jmap -histo [pid] # 按照内存使用大小倒序列出内存中的实例类型.

(3) jstack 查看线程栈:

jstack pid # 列出该 pid 对应 JVM 的全部线程栈描述, 主要包括每一个线程的状态以及堆栈内各栈帧的方法全限定名、代码位置. 注意: 这些信息的显示只是为了便于开发人员阅读, 并非栈中存的就是这些信息.

(4) jstat 实时查看堆内存的使用状况:

# 使用方法: 
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
# 查看可以使用的选项: 
jstat –options 
-class            # 类加载状况的统计
-compiler         # HotSpot中即时编译器编译状况的统计
-gc
-gccapacity       # 新生代、老年代以及永久代的存储容量状况
-gccause
-gcmetacapacity   # 元数据区的容量
-gcnew            # 新生代垃圾回收信息
-gcnewcapacity    # 新生代的存储容量
-gcold            # 老年代垃圾回收信息
-gcoldcapacity    # 老年代的存储容量
-gcutil           # 实时查看GC信息
-printcompilation # HotSpot编译方法的统计
  • 使用示例: 间隔5s, 每隔10条输出一次头信息, 打印进程号为3308的JVM进程的堆内存使用状况, 以及各代垃圾回收的次数及时间:
    jstat -gcutil -h10 77545 5000

  • 显示信息以下:

  • 参数说明:

    S0: Heap上的Survivor Space 0区已使用空间的百分比
    S1: Heap上的Survivor Space 1区已使用空间的百分比
    E:  Heap上的Eden Space区已使用空间的百分比
    O:  Heap上的Old Space区已使用空间的百分比
    M:  Meta Space(元数据区)已使用空间的百分比
    YGC: 从应用程序启动到采样时发生Young GC的次数
    YGCT: 从应用程序启动到采样时Young GC所用的时间(单位: 秒)
    FGC:  从应用程序启动到采样时发生Full GC的次数
    FGCT: 从应用程序启动到采样时Full GC所用的时间(单位: 秒)
    GCT:  从应用程序启动到采样时用于垃圾回收的总时间(单位: 秒)

2 查看 GC 日志信息

能够经过配置JVM的启动参数, 打印类的加载状况及对象的回收信息, 能够打印到屏幕或指定文件中, 默认也会打印到catalina.log中. Tomcat容器的JVM启动参数配置文件是: ${TOMCAT_HOME}/bin/catalina.sh, 具体参数以下:

-verbose:gc
# 在输出设备显示垃圾收集信息(JVM发生内存回收时输出相关信息)

-XX:+PrintGC
# 输出GC日志, 形式: Full GC 118250K->113543K(130112K), 0.0094143 secs 

-XX:+PrintGCDetails
# 输出GC详细日志, 形式: GC [DefNew: 8614K->781K(9088K), 0.0123035 secs] 118250K->113543K(130112K), 0.0124633 secs[Tenured: 112761K->10414K(121024K), 0.0433488 secs] 121376K->10414K(130112K), 0.0436268 secs] 

-XX:+PrintGCTimeStamps
# 输出GC的时间戳, 以基准时间的形式输出: 11.851: [GC 98328K->93620K(130112K), 0.0082960 secs], 11.851是JVM启动后的秒数.

-XX:+PrintGCDateStamps
# 输出GC的时间戳, 以日期的形式输出: 2018-08-28T21:53:59.234+0800

-XX:+PrintGCApplicationStoppedTime
# 打印垃圾回收期间程序暂停的时间, 即GC消耗的时间. 可与上面混合使用. 
# 输出形式: Total time for which application threads were stopped: 0.0468229 seconds

-XX:+PrintGCApplicationConcurrentTime
# 打印每次垃圾回收前, 程序未中断的执行时间, 即相邻2次GC的间隔. 
# 能够和上面的配置混合使用. 输出形式: Application time: 0.5291524 seconds 

-XX:+PrintTenuringDistribution
# 观察各个Age的对象总大小

-XX:PrintHeapAtGC
# 打印GC先后的详细堆栈信息

-XX:+HeapDumpOnOutOfMemoryError
# 发生OOM时自动dump堆栈信息, 以便后续分析

-Xloggc:../logs/gc.log
# 与上面选项配合使用, 将日志信息输出到指定的文件以便后续分析

3 添加 JMS 远程监控

对部署在局域网内其余服务器上的Tomcat, 能够打开JMX监控端口, 就能够在另外的服务器上经过该端口查看经常使用的参数(一些比较复杂的功能不支持).

配置方法: 一样是在JVM启动参数中配置, 配置以下:

-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Djava.rmi.server.hostname=172.16.11.62   # 设置JVM的JMS监听的IP地址, 防止错误监听为本机127.0.0.1地址
-Dcom.sun.management.jmxremote.port=1090  # 设置JVM的JMS监控的端口
-Dcom.sun.management.jmxremote.ssl=false  # 设置JVM的JMS监控不实用SSL
-Dcom.sun.management.jmxremote.authenticate=false  # 设置JVM的JMS监控不须要认证

参考资料

JVM 运行时内存使用状况监控

版权声明

做者: 马瘦风

出处: 博客园 马瘦风的博客

您的支持是对博主的极大鼓励, 感谢您的阅读.

本文版权归博主全部, 欢迎转载, 但请保留此段声明, 并在文章页面明显位置给出原文连接, 不然博主保留追究相关人员法律责任的权利.

相关文章
相关标签/搜索