JVM Monitor

摘要: jvm monitor

正文:

JVM 监控

基于 jstack 监控定位

查看CPU负载

  • 系统负载/ CPU负载 - 是Linux系统中CPU过度使用率或利用率不足的度量; CPU正在执行或处于等待状态的进程数。
  • 负载平均值 - 是在给定的1,5和15分钟时间段内计算的平均系统负载。
  • top 命令 (定位到我们cpu高的进程)
$ top
top - 16:40:59 up 388 days,  1:04,  1 user,  load average: 0.00, 0.01, 0.05
Tasks:  75 total,   1 running,  72 sleeping,   0 stopped,   2 zombie
%Cpu(s):  0.7 us,  0.3 sy,  0.0 ni, 99.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1883492 total,   247312 free,   473204 used,  1162976 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  1188144 avail Mem 

$ uptime
 16:42:36 up 388 days,  1:06,  1 user,  load average: 0.00, 0.01, 0.05

其中 load average 代表的是cpu的平均负载,三个数字分别代表1分钟、5分钟、15分钟内cpu的平均负载。 负荷的大小跟cpu个数以及当前负荷有关系,例如1h 处理器,负载为5 则大概表面有1成的在running 4成的在等待,也就意味着此时可能服务器已经无法处理新的请求了,系统也就凉咯 查看cpu个数

$ cat /proc/cpuinfo | grep "cpu cores" 

定位具体线程

  • jstack 命令 例如我们由top定位到了某个异常的进程,拿到了pid,为9048 接下来我们使用 jstack 命令导出 9048 进程中线程栈的信息
$ jstack 9048 > 9048.txt
$ top -p 9048 -H # 拿到所有线程的cpu信息,定位具体线程pid
9243 root      20   0 2498028  59096   7008 S  91.0  3.1   0:00.00 java           
9244 root      20   0 2498028  59096   7008 S  99.0  3.1   0:00.32 java
# 定位到线程pid为 9243 9244的cpu占用高
$ printf "%x" 9243 # 转为16进制--> 2353
$ printf "%x" 9244 # 转为16进制--> 2354
# 在9048.txt 查找nid为 0x2353 和 0x2354的线程栈信息,最后发现是nio的WindowsSelectorImpl导致的
$ cat 9048.txt

"http-nio-8499-ClientPoller-0" #27 daemon prio=5 os_prio=0 tid=0x4e69c800 nid=0x2353 runnable [0x5108f000]
   java.lang.Thread.State: RUNNABLE
	at sun.nio.ch.WindowsSelectorImpl.resetWakeupSocket0(Native Method)
	at sun.nio.ch.WindowsSelectorImpl.resetWakeupSocket(Unknown Source)
	- locked <0x257756d8> (a java.lang.Object)
	at sun.nio.ch.WindowsSelectorImpl.doSelect(Unknown Source)
	at sun.nio.ch.SelectorImpl.lockAndDoSelect(Unknown Source)
	- locked <0x257756b8> (a sun.nio.ch.Util$2)
	- locked <0x257756a8> (a java.util.Collections$UnmodifiableSet)
	- locked <0x2575d518> (a sun.nio.ch.WindowsSelectorImpl)
	at sun.nio.ch.SelectorImpl.select(Unknown Source)
	at org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:744)
	at java.lang.Thread.run(Unknown Source)

   Locked ownable synchronizers:
	- None 

基于 JvisualVM 的可视化监控

本地监控

打开 JDK 安装目录 bin 文件夹下的 jvisualvm.exe ,在左侧的本地下可以看到正常运行的java 应用,除了正常的类似命令行界面化的操作外,我们可以安装别的好用的插件

  1. 工具–插件–设置–编辑 将URL修改为 https://visualvm.github.io/pluginscenters.html 中对应的JDK版本下的地址,如JDK 8 Update 131 - 192 https://visualvm.github.io/uc/8u131/updates.xml.gz
  2. 切换TAB至可用插件,在其列表中选中 Visual GC 插件安装后重启jvisualvm.exe 即可看到多出的 Visual GC Tab

远程监控

监控远程Tomcat

  • 修改 Catalina.sh 文件
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=xx -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.net.preferlPv4Stack=true -Djava.rmi.server.hostname=xx.xx.xx.xx" 

监控远程普通java进程

  • 添加启动参数
 nohup java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=xx -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.net.preferlPv4Stack=true -Djava.rmi.server.hostname=xx.xx.xx.xx -jar xx.jar & 

JvisualVM 参考链接

基于Btrace的监控调试

Btrace可用动态的向目标应用程序的字节码注入追踪代码

下载安装

  • 下载安装包 https://github.com/btraceio/btrace 下载realse版本我这里是 v1.3.11.3
  • 解压并配置环境变量 新增环境变量 BTRACE_HOME ,Path 中追加 %BTRACE_HOME%\bin

运行方式

  • JVisualVM 中添加Btrace插件,添加 classpath
  • 使用命令行 btrace <pid> <trace_script>

使用方法

Demo

这里举在JVisualVM 中使用的例子,安装完Btrace插件后,对其中的 java 应用列表右键打开Trace application,例如对某个应用的某个查询方法的脚本如下:

import com.sun.btrace.AnyType;
import com.sun.btrace.BTraceUtils;
import com.sun.btrace.annotations.BTrace;
import com.sun.btrace.annotations.Kind;
import com.sun.btrace.annotations.Location;
import com.sun.btrace.annotations.OnMethod;
import com.sun.btrace.annotations.ProbeClassName;
import com.sun.btrace.annotations.ProbeMethodName;

@BTrace
public class PrintArgDemo {
	
	@OnMethod(
		clazz="com.clamc.climb.admin.web.UserController",
		method="query",
		location=@Location(Kind.ENTRY)
	)
	public static void queryTest(@ProbeClassName String className, @ProbeMethodName String methodName, AnyType[] args) {
		BTraceUtils.printArray(args);
		BTraceUtils.println(className + " " + methodName);
		BTraceUtils.println();
	}
}

勾上 Output Class-Path (Class-Path 可以用来增加第三方jar包),点击 Start 即可等待执行到 query 方法后的打印输出

Doc

  • 普通方法 @OnMethod(clazz=””,method=””)
  • 构造方法 @OnMethod(clazz=””,method=”“)
  • 重载方法通过参数区分
  • Kind 拦截时机
    • Kind.ENTRY 入口,默认值
    • Kind.RETURN 返回
    • Kind.THROW 异常
    • Kind.Line 行
  • this: 形参+@Self 可以拦截this对象
  • 复杂的参数可以通过反射获取
  • printXxx()

注意事项

  • 默认只能本地运行
  • 生产环境下也可以使用,但是被修改的字节码不会被还原

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Method的invoke方法源码分析

    itliusir
  • MySQL5.7安装常见问题

    itliusir
  • Docker Notes-introduction

    摘要: Docker Notes系列为学习Docker笔记,本文是Docker总体介绍

    itliusir
  • Java中,成员内部类的常见修饰符及应用 && 成员内部类不是静态的,访问的格式

    成员内部类的常见修饰符及应用:   private    为了保证数据的安全性   static      为了方便访问数据   注意:静态的内...

    黑泽君
  • 核心网的演进(RCAF,PFDF和TSSF)——3GPP REST接口

    回首技术发展的多样性,从3GPP Release 13开始,标准已经走上了一条新路。更关注新的网络元素,广泛关注机器类型通信(MTC)、新的基于REST的接口(...

    SDNLAB
  • JavaScript深入浅出补充——(一)数据类型,表达式和运算符

    项目基本做完,在进行下一阶段学习之前先看视频学习回顾一下JavaScript 一、数据类型 JavaScript中有五种原始类型和一种对象类型 ? JavaSc...

    二十三年蝉
  • 【Rust日报】 2019-09-09:glint 用Rust編寫的commit 提示工具

    然後再用 Linux perf 跑看看,發現分析結果與 cargo-profiler 相同

    MikeLoveRust
  • CSS和网络性能

    CSS对于呈现页面至关重要 - 在找到,下载和解析所有CSS之前,浏览器不会开始呈现 - 因此我们必须尽可能快地将其加载到用户的设备上。 关键路径上的任何延迟都...

    frontoldman
  • R语言_方差分析

    在回归分析中,通过量化的预测变量来预测量化的响应变量,建立了相应的回归模型。 同时,预测变量也不一定是量化的,还可以是名义型或者有序型变量。这种情况下,关注...

    用户1147754
  • 前端-CSS与网络性能

    在博客上,CSS 相关的文章却不多。那就结合 CSS 与性能这两大主题,为大家带来一篇文章吧。

    grain先森

扫码关注云+社区

领取腾讯云代金券