SkillAgentSearch skills...

Monitor

java生产环境内存调优(包括jvm参数类型,JVM的参数类型 jinfo & jps(参数和进程查看) jstat(类加载、垃圾收集、JIT 编译) jmap+MAT(内存溢出) jstack(线程、死循环、死锁) JVisualVM(本地和远程可视化监控) 使用 BTrace 进行拦截调试 Tomcat 性能监控与调优 Nginx 性能监控与调优 JVM 层 GC 调优 JAVA代码层调优 )欢迎:star2::star2::star2::star2::star2::star2::star2::star2:

Install / Use

/learn @vipcolud/Monitor
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

主要内容包括

| :blue_heart:|:blue_heart:|:blue_heart: |:blue_heart:|:blue_heart:|:blue_heart:| | -------- | :----: | :----: |:----: |:----: |:----: | | jvm参数类型:alien:|jinfo & jps(参数和进程查看):alien:|jstat(类加载、垃圾收集、JIT 编译):alien: |jmap+MAT(内存溢出):alien:|jstack(线程、死循环、死锁):alien:|JVisualVM(本地和远程可视化监控:alien:| |使用 BTrace进行拦截调试:alien:|Tomcat 性能监控与调优:alien:| Nginx 性能监控与调优:alien:|JVM 层 GC 调优:alien:|JAVA代码层调优:alien: |:alien:|

1.JVM的参数类型

标准参数(各版本中保持稳定)
-help
-server -client
-version -showversion
-cp -classpath
X 参数(非标准化参数)
-Xint:解释执行
-Xcomp:第一次使用就编译成本地代码
-Xmixed:混合模式,JVM 自己决定是否编译成本地代码

示例:

java -version(默认是混合模式)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)
java -Xint -version
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, interpreted mode)
XX 参数(非标准化参数)
主要用于 JVM调优和 debug
Boolean类型(+-)
格式:-XX:[+-]<name>表示启用或禁用 name 属性
如:-XX:+UseConcMarkSweepGC(启用cms垃圾收集器)
-XX:+UseG1GC(启用G1垃圾收集器)
非Boolean类型(key-value)(带=的)
格式:-XX:<name>=<value>表示 name 属性的值是 value
如:-XX:MaxGCPauseMillis=500(GC最大停用时间)
-xx:GCTimeRatio=19
-Xmx -Xms属于 XX 参数
-Xms 等价于-XX:InitialHeapSize(初始化堆大小)
-Xmx 等价于-XX:MaxHeapSize    (最大堆大小)
-xss 等价于-XX:ThreadStackSize(线程堆栈)
查看
jinfo -flag MaxHeapSize <pid>(查看最大内存)
-XX:+PrintFlagsInitial
-XX:+PrintFlagsFinal
-XX:+UnlockExperimentalVMOptions 解锁实验参数
-XX:+UnlockDiagnosticVMOptions 解锁诊断参数
-XX:+PrintCommandLineFlags 打印命令行参数
输出结果中=表示默认值,:=表示被用户或 JVM 修改后的值
示例:java -XX:+PrintFlagsFinal -version

2.jinfo & jps(参数和进程查看)

pid 可通过类似 ps -ef|grep tomcat或 jps来进行查看
jps
[详情参考 jps官方文档](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jps.html)
-l
jinfo
jinfo -flag MaxHeapSize <pid>
jinfo -flags <pid>

jstat
[详情参考 jps官方文档](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html#BEHBBBDJ)
jstat 使用示例
3.jstat(类加载、垃圾收集、JIT 编译)
类加载
每隔1000ms 即1秒,共输出10次
jstat -class <pid> 1000 10
loaded 加载类的个数
[root@localhost java]# jps
4167 Jps
3370 Bootstrap
[root@localhost java]# jstat -class 3370
Loaded  Bytes  Unloaded  Bytes     Time
  5990 12028.7        0     0.0      15.50
垃圾收集
[root@localhost java]# jstat -gc 3370
Warning: Unresolved Symbol: sun.gc.metaspace.capacity substituted NaN
Warning: Unresolved Symbol: sun.gc.metaspace.used substituted NaN
Warning: Unresolved Symbol: sun.gc.compressedclassspace.capacity substituted NaN
Warning: Unresolved Symbol: sun.gc.compressedclassspace.used substituted NaN
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
1600.0 1600.0  0.0   1600.0 13184.0   7779.2   32696.0    22669.8     -      -      -      -       117    1.056   5      0.386    1.441
-gc, -gcutil, -gccause, -gcnew, -gcold
jstat -gc <pid> 1000 10
以下大小的单位均为 KB
S0C, S1C, S0U, S1U: S0和 S1的总量和使用量
EC, EU: Eden区总量与使用量
OC, OU: Old区总量与使用量
MC, MU: Metacspace区(jdk1.8前为 PermGen)总量与使用量
CCSC, CCSU: 压缩类区总量与使用量
YGC, YGCT: YoungGC 的次数与时间
FGC, FGCT: FullGC 的次数与时间
GCT: 总的 GC 时间
JIT 编译
-compiler, -printcompilation
[root@localhost java]# jstat -compiler 3370
Compiled Failed Invalid   Time   FailedType FailedMethod
     833      0       0    26.04          0
    花费26.04s编译了833个方法

4.jmap+MAT(内存溢出)

内存溢出演示: 生成springboot初始化代码 最终代码

为快速产生内存溢出,右击 Run As>Run Configurations, Arguments 标签VM arguments 中填入
-Xmx32M -Xms32M
访问 http://localhost:8080/heap
Exception in thread "http-nio-8080-ClientPoller-0" java.lang.OutOfMemoryError: GC overhead limit exceeded
    at java.util.HashMap$KeySet.iterator(HashMap.java:916)
    at java.util.HashSet.iterator(HashSet.java:172)
    at java.util.Collections$UnmodifiableCollection$1.<init>(Collections.java:1039)
Exception in thread "http-nio-8080-exec-1" java.lang.OutOfMemoryError: GC overhead limit exceeded
-XX:MetaspaceSize=32M -XX:MaxMetaspaceSize=32M(同时在 pom.xml 中加入 asm 的依赖)
访问 http://localhost:8080/nonheap
Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
Exception in thread "ContainerBackgroundProcessor[StandardEngine[Tomcat]]" java.lang.OutOfMemoryError: Metaspace
内存溢出自动导出
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./
右击 Run As>Run Configurations, Arguments 标签VM arguments 中填入
-Xmx32M -Xms32M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./
可以看到自动在当前目录中生成了一个java_pid660.hprof文件
java.lang.OutOfMemoryError: GC overhead limit exceeded
Dumping heap to ./java_pid660.hprof ...
另一种导出溢出也更推荐的方式是jmap
option: -heap, -clstats, -dump:<dump-options>, -F
jmap -dump:format=b,file=heap.hprof <pid>
C:\Users\Mr Chen>jps -l
10476 sun.tools.jps.Jps
6744
14980 com.imooc.monitor_tuning.MonitorTuningApplication
C:\Users\Mr Chen>cd desktop
C:\Users\Mr Chen\Desktop>jmap -dump:format=b,file=heap.hprof 14980
Dumping heap to C:\Users\Mr Chen\Desktop\heap.hprof ...
Heap dump file created

jmap 导出溢出文件 MAT下载地址 找开上述导出的内存溢出文件即可进行分析,如下图的溢出源头分析: Memory Analyzer 内存溢出分析

5.jstack(线程、死循环、死锁)

1.线程状态
jstack: 打印jvm内部所有线程
C:\Users\Mr Chen\Desktop>jps -l
15260 com.imooc.monitor_tuning.MonitorTuningApplication
10836 sun.tools.jps.Jps
6744
C:\Users\Mr Chen\Desktop>jstack 15260> 15260.txt

可查看其中包含java.lang.Thread.State: WAITING (parking),JAVA 线程包含的状态有: NEW:线程尚未启动 RUNNABLE:线程正在 JVM 中执行 BLOCKED:线程在等待监控锁(monitor lock) WAITING:线程在等待另一个线程进行特定操作(时间不确定) TIMED_WAITING:线程等待另一个线程进行限时操作 TERMINATED:线程已退出

2.死循环导致cpu飙高
monitor_tuning中新增CpuController.java
直接 maven clean、 maven install
此时会生成一个monitor_tuning-0.0.1-SNAPSHOT.jar的 jar包,为避免本地的 CPU 消耗过多导致死机,建议上传上传到虚拟机进行测试
nohup java -jar monitor_tuning-0.0.1-SNAPSHOT.jar &
访问 http://xx.xx.xx.xx:8080/loop(端口8080在application.properties文件中定义)
top -p <pid> -H可以查看线程及 CPU 消耗情况
top 命令打出线程 CPU 消耗

使用 jstack <pid>可以导出追踪文件,文件中 PID 在 jstack 中显示的对应 nid 为十六进制(命令行可执行 print '%x' <pid>可以进行转化,如4008对应的十六进制为1007)

[root@localhost java]# jstack 4008 > 4008.txt
[root@localhost java]# printf "%x" 4103
1007[root@localhost java]# jstack 4103 > 4103.txt
"http-nio-8080-exec-7" #22 daemon prio=5 os_prio=0 tid=0x00007f6378be7000 nid=0x1026 runnable [0x00007f63556d1000]
   java.lang.Thread.State: RUNNABLE
    at java.lang.String.indexOf(String.java:1769)
    at java.lang.String.indexOf(String.java:1718)
    at com.imooc.monitor_tuning.chapter2.CpuController.getPartneridsFromJson(CpuController.java:73)

说明getPartneridsFromJson这里导致的cpu飙升

3.死锁

访问http://xx.xx.xx.xx:8080/deadlock(如上jstack <pid>导出追踪记录会发现如下这样的记录)

[root@localhost java]# ps -ef |grep  java
root       4357   3145 23 02:00 pts/0    00:01:22 java -jar monitor_tuning-0.0.1-SNAPSHOT.jar
root       4474   3707  0 02:06 pts/3    00:00:00 grep --color=auto java
[root@localhost java]# jstack 4357 > 4357.txt

将文件拉到最后会发现

"Thread-5":
    at com.imooc.monitor_tuning.chapter2.CpuController.lambda$deadlock$1(CpuController.java:41)
    - waiting to lock <0x00000000f6b383e0> (a java.lang.Object)
    - locked <0x00000000f6b383f0> (a java.lang.Object)
    at com.imooc.monitor_tuning.chapter2.CpuController$$Lambda$337/678439847.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)
"Thread-4":
    at com.imooc.monitor_tuning.chapter2.CpuController.lambda$deadlock$0(CpuController.java:33)
    - waiting to lock <0x00000000f6b383f0> (a java.lang.Object)
    - locked <0x00000000f6b383e0> (a java.lang.Object)
    at com.imooc.monitor_tuning.chapter2.CpuController$$Lambda$336/498593401.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)
Found 1 deadlock.

线程4在等待线程5,同时线程5也在等待线程4,此时死锁

6.JVisualVM(本地和远程可视化监控)

1.监控本地java进程

详情参考官方文档 Mac命令行直接输入jvisualvm命令,Windows 找到对应的 exe 文件双击即可打开 插件安装Tools>Plugins>Settings根据自身版本(java -version)更新插件中心地址,各版本查询地址: jvisualvm插件 建议安装:Visual GC, BTrace Workbench

2.监控远程java进程

以上是本地的JAVA进程监控,还可以进行远程的监控,在上图左侧导航的 Applications 下的 Remote 处右击Add Remote Host...,输入主机 IP 即可添加,在 IP 上右击会发现有两种连接 JAVA 进程进行监控的方式:JMX, jstatd

vi bin/catalina.sh(以192.168.73.0为例)
:/JAVA_OPTS 按两个n 添加
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9004 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.net.preferIPv4Stack=true -Djava.rmi.server.hostname=192.168.73.0"

报错 异常情况:VisualVM 无法使用 service:jmx:rmi:///jndi/rmi:///jmxrmi 连接到 原因: 除了JMX server指定的监听端口号外,JMXserver还会监听一到两个随机端口号, 可以通过命grep <pid> 来查看当前java进程需要监听的随机端口号

[root@localhost bin]# jps
4216 Jps
4031 Bootstrap
[root@localhost bin]# lsof -i|grep java | grep 4031
java      4031    root   19u  IPv4  32304      0t0  TCP *:33707 (LISTEN)
java      4031    root   20u  IPv4  32310      0t0  TCP *:9004 (LISTEN)
java      4031    root   21u  IPv4  32322      0t0  TCP *:50022 (LISTEN)
java      4031    root   53u  IPv4  32323      0t0  TCP *:webcache (LISTEN)
java      4031    root   57u  IPv4  32325      0t0  TCP *:8009 (LISTEN)
java      4031    root   69u  IPv4  32338      0t0  TCP localhost:mxi (LISTEN)
将监听的端口去掉防火墙当然9004端口也是需要去掉的
[root@localhost bin]# iptables -I INPUT -p tcp --dport 33707 -j ACCEPT
[root@localhost bin]# iptables -I INPUT -p tcp --dport 50022 -j ACCEPT
[root@localhost bin]# iptables -I INPUT -p tcp --dport 8009 -j ACCEPT

启动tomcat,以 JMX 为例,在 IP 上右击点击Add JMX Connection...,输入 192.168.73.0:9004 Add JMX Connection 以上为 Tomcat,其它 JAVA 进程也是类似的,如:

nohup java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9005 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.net.preferIPv4Stack=true -Djava.rmi.server.hostname=192.168.73.0 -jar monitor_tuning-0.0.1-SNAPSHOT.jar &

6.使用 BTrace 进行拦截调试

下载BTrace 可以动态地向目标应用程序的字节码注入追踪代码,使用的技术有 JavaCompilerApi, JVMTI, Agent, Instrumentation+ASM 使用方法:JVisualVM中添加 BTrace 插件 方法二:btrace <pid> <trace_script> monitor_tuning中新增包org.alanhou.monitor_tuning.chapter4 安装BTrace 要记得配置环境变量,以 windos 为例

BTRACE_

Related Skills

View on GitHub
GitHub Stars243
CategoryDevelopment
Updated6d ago
Forks93

Languages

Java

Security Score

80/100

Audited on Mar 24, 2026

No findings