jvm实战

tools ref

  • 2-1
java -version
java -Xint -version

ps -ef | grep tomcat
jinfo -flag MaxHeapSize 74691
jinfo -flag ThreadStackSize 74691 # -xss
  • 2-2
java -XX:+PrintFlagsFinal -version  #约700多个参数
jps -l
  58274 sun.tools.jps.Jps
  74691 org.apache.catalina.startup.Bootstrap
jinfo -flag MaxHeapSize 74691
  -XX:MaxHeapSize=2147483648
jinfo -flags 74691 #手动赋值过或脚本设置过的参数
  Non-default VM flags: -XX:CICompilerCount=3 ...
jinfo -flag UseConcMarkSweepGC 74691 #is enabled cms
  -XX:-UseConcMarkSweepGC
jinfo -flag UseG1GC 74691
  -XX:-UseG1GC
jinfo -flag UseParallelGC 74691
  -XX:+UseParallelGC
  • 2-3
jstat -class 74691
  Loaded  Bytes  Unloaded  Bytes     Time   
    3669  7848.4        0     0.0       3.66
jstat -gc 74691
   S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
  11776.0 12800.0 2652.1  0.0   29184.0  17214.6   65536.0    15089.2   25856.0 25214.5 2816.0 2624.6     12    0.091   1      0.053    0.144
jstat -gc 74691 1000 10  #每秒1次 10次
jstat -compiler 74691
  Compiled Failed Invalid   Time   FailedType FailedMethod
      2704      1       0     6.97          1 org/apache/tomcat/util/IntrospectionUtils setProperty
  • 2-4
    • jdk8 Metaspace 调优
# 堆溢出
死循环:生成用户对象,加入list中
运行vm参数`-Xms32M -Xmx32M`
  Exception in thread "http-nio-8080-exec-3" java.lang.OutOfMemoryError: GC overhead limit exceeded
  Exception in thread "Catalina-utility-2" java.lang.OutOfMemoryError: GC overhead limit exceeded
---
# 非堆溢出
死循环:依赖`asm core`动态生成Class,加入list中
运行vm参数`-XX:MetaspaceSize=32M -XX:MaxMetaspaceSize=32M`
  Exception in thread "http-nio-8080-exec-1" java.lang.OutOfMemoryError: Metaspace
  • 2-5 导出内存映像文件
    • -XX:+HeapDumpOnOutOfMemoryError
      -XX:HeapDumpPath=./

    • jmap -dump:format=b,file=heap.hprof 5566
#自动导出
运行vm参数 `-Xms32M -Xmx32M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./`
  java.lang.OutOfMemoryError: GC overhead limit exceeded
  Dumping heap to ./java_pid1948.hprof ...
  Heap dump file created [44124222 bytes in 0.346 secs]
  Exception in thread "http-nio-8080-exec-1" java.lang.OutOfMemoryError: GC overhead limit exceeded

#手动导出
jmap  -help
jps -l
  5566 com.asvgo.monitor_tuning.MonitorTuningApplication
cd ~/hprof
jmap -dump:format=b,file=heap.hprof 5566
  Dumping heap to /Users/xianfan/hprof/heap.hprof ...
  Heap dump file created

jmap -heap 5566 #每一区块占用内存情况
  • 2-6 MAT分析内存溢出
# 下载安装 Eclipse Memory Analyzer
# 文件打开之前的.hprof文件分析
1. 查看对象数量 
  `正则表达式筛选包名`
  `右键 - Merge shortest Path to GC Roots - exclude all phantom/weak/soft etc. references 排除弱引用`
2. 查看对象占用字节数

2-7 jstack与线程的状态

jps -l
jstack 33143 > 33143.txt `包含每个线程的信息,包括线程池,GC等`
top -pid 33143 -h

2-8 jstack实战死循环与死锁 cpu飙高问题

  • 多么痛的领悟
`死循环`
写死循环程序  CpuController#loop
多个浏览器窗口访问loop
top查看 `load average:`
jstack 7930 > 7930.txt
top -p 7930 -H
printf "%x" 8247 `转十六进制`
  2037

`死锁`
写死锁程序  CpuController#deadlock
ps -ef | grep java `找到程序进程id`
jstack 23674 > 23674.txt
定位到`Found 1 deadlock.`
  • 3-1 监控本地java进程 jvisualvm
$JAVA_HOME/bin/jvisualvm
工具-->配置插件中心: https://visualvm.github.io/pluginscenters.html
安装插件`visualGC`
  • 3-2 监控远程的java进程 jvisualvm+JMX连接
远程-->添加远程主机
修改tomcat/bin/Catalina.sh
    JAVA_OPTS="JAVA_OPTS 
        -Dcom.sun.management.jmxremote
        -Dcom.sun.management.jmxremote.port=9004
        -Dcom.sun.management.jmxremote.authenticate=false
        -Dcom.sun.management.jmxremote.sll=false
        -Djava.net.preferIPv4Stack=true
        -Djava.rmi.server.hostname=10.120.3.6`
        "

./bin/startup.sh    `重启`
tail -f ./logs/catalina.out

`client` 在主机上右键-->添加JMX连接,设置端口9004

---
监控远程普通应用进程
`启动应用 ->` nohup java -Dcom.sun.management.jmxremote
        -Dcom.sun.management.jmxremote.port=9005
        -Dcom.sun.management.jmxremote.authenticate=false
        -Dcom.sun.management.jmxremote.sll=false
        -Djava.net.preferIPv4Stack=true
        -Djava.rmi.server.hostname=10.120.3.6 -jar monitor_tuning.jar
tail -f nohup.out

`client` 在主机上右键-->添加JMX连接,设置端口9005

4-1 btrace入门

  • 在不修改程序的前提下,动态获取某个类的某个方法的参数,不局限于controller
  • 只能在本机执行
github: https://github.com/btraceio/btrace
设置环境变量 BTRACE_HOME
两种运行脚本方式:
  1. 使用命令行btrace  
  2. 在JVisualVM中添加 `Btrace Workbench` 插件,添加classpath

btrace能力:
  在不修改程序的前提下,动态获取某个类的某个方法的参数,不局限于controller
#1
编写脚本 `PrintArgSimple.java`
jps -l
btrace 13348 PrintArgSimple.java

#2
在JVisualVM的进程菜单上右键-->Trace application-->手动编写btrace脚本
  • 4-2 拦截构造函数、同名函数
如何拦截构造函数
  编写代码Ch4Controller#constructor
  编写btrace脚本PrintConstructor.java
如何拦截同名函数
  编写代码Ch4Controller
  编写btrace脚本PrintSame.java
  • 4-3 拦截返回值、异常、行号
编写btrace脚本PrintReturn.java
编写异常源码ch4#exception 、 脚本PrintOnThrow
编写脚本PrintLine,判断某行是否执行了
  • 4-4 拦截复杂参数、坏境变量、正则匹配拦截
获取对象值
  简单类型:直接获取
  复杂类型:反射,类名+属性名

编写源码ch4#arg2 、 编写脚本PrintArgComplex
jps -l
btrace  PrintArgComplex.java
  抛错,找不到User类
btrace -cp "User的class文件所在目录"  PrintArgComplex.java

编写正则表达式脚本 PrintRegex.java
  method="/.*/"  表示匹配任意方法

编写脚本 PrintJInfo.java 打印环境变量
  类似 jinfo -sysprops
  • 4-5 注意事项
默认只能本地运行
生产环境下可以使用,但被修改的字节码不会被还原
  • 5-1 tomcat远程debug
jdwp
rz
sz
  • 5-2 tomcat-manager监控

  • 5-3 psi-probe监控

你可能感兴趣的:(jvm实战)