用javaagent和javassist实现Arthas的watch功能
一、被监控的服务 spring-boot-demo
1、 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.techhf</groupId><artifactId>spring-boot-demo</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.3.4.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-undertow</artifactId><version>2.3.4.RELEASE</version></dependency></dependencies></project>
2、DemoController
package com.techhf.demo.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author shiweijia* @date 2024/8/1 17:31*/
@RequestMapping("/demo")
@RestController
public class DemoController {@RequestMapping("/hello")public String hello(String name) {return "hello world " + name;}}
3、DemoApplication
package com.techhf.demo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** @author shiweijia* @date 2024/8/1 17:30*/
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}
4、运行DemoApplication
-javaagent:D:/temp/jvm-agent-1.0-SNAPSHOT-jar-with-dependencies.jar

二、jvm-agent

1、pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.techhf</groupId><artifactId>jvm-agent</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.30.2-GA</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><version>3.3.0</version><configuration><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs><archive><manifestEntries><Premain-Class>com.techhf.agent.WatchAgent</Premain-Class><Agent-Class>com.techhf.agent.WatchAgent</Agent-Class><Can-Redefine-Classes>true</Can-Redefine-Classes><Can-Retransform-Classes>true</Can-Retransform-Classes></manifestEntries></archive></configuration><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins></build></project>
2、WatchAgent
package com.techhf.agent;import java.lang.instrument.Instrumentation;/*** @author shiweijia* @date 2024/8/1 16:00*/
public class WatchAgent {public static void premain(String agentArgs, Instrumentation inst) {agentArgs = "com.techhf.demo.controller.DemoController,hello";System.out.println("premain attached with args: " + agentArgs);transform(agentArgs, inst);}public static void agentmain(String agentArgs, Instrumentation inst) {System.out.println("agentmain attached with args: " + agentArgs);transform(agentArgs, inst);}private static void transform(String agentArgs, Instrumentation inst) {// 解析 agentArgs 来获取类名和方法名String[] parts = agentArgs.split(",");String className = parts[0];String methodName = parts[1];inst.addTransformer(new WatchTransformer(className, methodName));}}
3、WatchTransformer
package com.techhf.agent;import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;/*** @author shiweijia* @date 2024/8/3 16:56*/
public class WatchTransformer implements ClassFileTransformer {private String className;private String methodName;public WatchTransformer(String className, String methodName) {this.className = className;this.methodName = methodName;}@Overridepublic byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {className = className.replace('/', '.');if (this.className.equals(className)) {try {ClassPool pool = ClassPool.getDefault();CtClass cc = pool.get(className);CtMethod method = cc.getDeclaredMethod(methodName);String beforeCode = "{ System.out.print(\"Before Method Name: \" + \"" + method.getName() + "\" + \", Parameters: \"); " +"for (int i = 0; i < $args.length; i++) { " +" System.out.print($args[i]); " +"} " +"System.out.println(); }";method.insertBefore(beforeCode);method.insertAfter("{ System.out.println(\"After Method Name: \"+\"" + method.getName()+ "\" + \", Return: \" + $_); }");return cc.toBytecode();} catch (Exception e) {e.printStackTrace();}}return classfileBuffer;}
}
三、启动时监控
如上述实例,运行时加入-javaagent相关参数即可。
四、运行时监控
import com.sun.tools.attach.VirtualMachine;/*** @author shiweijia* @date 2024/8/1 17:35*/
public class AttachLoader {public static void main(String[] args) {if (args.length < 2) {System.out.println("Usage: AttachLoader <pid> <agent-path> <agent-args>");System.exit(1);}String pid = args[0];String agentPath = args[1];String agentArgs = args[2];try {// 获取目标 JVM 进程VirtualMachine vm = VirtualMachine.attach(pid);vm.loadAgent(agentPath, agentArgs);// 可选:在需要时分离(detach)// vm.detach();System.out.println("Agent loaded into PID " + pid);} catch (Exception e) {e.printStackTrace();}}}
运行参数为:
34496 D:\temp\jvm-agent-1.0-SNAPSHOT-jar-with-dependencies.jar com.techhf.demo.controller.DemoController,hello
采用运行时监控需要注意:spring 是动态代理的,agentmain无法直接监控具体的类。需要优化相关的实现。
相关文章:
用javaagent和javassist实现Arthas的watch功能
一、被监控的服务 spring-boot-demo 1、 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation&q…...
golang 图片转1bit color bmp图片
问题背景 一些打印机需要的都是1bit color bmp图片,但是golang中没有直接的办法,官方image库最低bpp为8,打印机无法使用。 在github上找到了很多资源,都没有直接能转的,突然看到一个老外,可以支持plattered图片转位1bit color bmp图片,然后自己先把图片转位plattered黑…...
Leetcode75-5 反转字符串的元音字母
本质上来说就是反转字符串 一部分需要反转 一部分不动 思路: 1.用String字符串倒序拼接 就是过滤掉不是元音字符 然后把所有的字符(非元音的直接复制过来 元音字母直接从反转的字符串里边复制即可) 2.看了题解发现自己写的啰嗦了 就是一个双指针问题用…...
static关键字在Java中的作用与用法
static关键字在Java中的作用与用法 大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿! 在Java中,static关键字是一个非常重要的概念,用于定义静态成员、方法和内部类。它的使用可…...
50etf期权行权采用什么交割方式 ?
50ETF期权是欧式期,要到期日当天才能行权交制,其交割方式是实物交割买卖双方在到期行权日时需要准备一手交钱,一手收货或是一手交,一手收钱,如果持有期权到达到期日之前,投资者认为行权并不划算,…...
ts-node 报错 ERR_UNKNOWN_FILE_EXTENSION
问题 有个monorepo项目,在最外层一次性打包 3 个项目的脚本已经成功实现,如下: "build:test": "cross-env NODE_ENVtest vite build --mode test && esno ./build/script/postBuild.ts", "build:prod"…...
水域救援设备,保护水域安全_鼎跃安全
季作为一年中最炎热的季节,不仅带来了难耐的高温,也悄然间加剧了水域安全问题的严峻性。这一时期,正值学生群体享受悠长暑假的宝贵时光,他们往往倾向于寻找清凉之地以解酷暑,水域因此成为了不少学生的首选之地。然而&a…...
openmetadata本地编译环境搭建
openmetadata本地编译环境搭建 本地环境: Docker 20 or higher Java JDK 17 Antlr 4.9.2 - sudo make install_antlr_cli JQ - brew install jq (osx) apt-get install jq (Ubuntu) Maven 3.5.x or higher - (with Java JDK 11) Python 3.7, 3.8 or 3.9 Node…...
LeetCode Hard|【25. K 个一组翻转链表】
力扣题目链接 首先我们考虑一种很直观的思路: 遍历链表,统计链表长度遍历链表,进行翻转 对于每一组长度为 K 的节点,进行翻转如果剩余节点不足 K 个,则不进行翻转 连接翻转后的子链表 这里我们用的就是只用 O(1) 额外内…...
python爬虫预备知识三-多进程
python实现多进程的方法:fork、multiprocessing模块创建多进程。 os.fork方法 os.fork方法只适合于unix/linux系统,不支持windows系统。 fork方法调用一次会返回两次,原因在于操作系统将当前进程(父进程)复制出一份…...
【zlm】针对单个设备的音频的编码的设置
目录 结论 原理 测试 结论 为了防止zlm音频配置里设置成opus优先,在国标推流时,调用push时,默认加上codecpcma 如下 https://10.60.100.196:10443/index/api/webrtc?applive&streamtest&typepush&codecpcma 原理 测试 …...
文案人的梦工场,网易入职指南!
网易云对于咱们一些有点文艺的文案策划来说,简直就是梦中情司。 在这里工作锻炼机会很多,也很开拓眼界,能获得相当于在别处3倍能力的成长速度,福利待遇也是很好的。 要进入网易云音乐做文案策划,你可以按照以下步骤进…...
做一个能和你互动玩耍的智能机器人之七-接入对话和大模型
接入科大迅飞的语音识别: private void printResult(RecognizerResult results) {String text JsonParser2.parseIatResult(results.getResultString());String sn null;// 读取json结果中的sn字段try {JSONObject resultJson new JSONObject(results.getResult…...
阿里巴巴商家联系方式采集软件使用教程
以下是一个批量访问阿里巴巴商家店铺的Python代码示例: import requestsdef visit_shop(shop_url):try:response requests.get(shop_url)if response.status_code 200:print(f"成功访问店铺:{shop_url}")else:print(f"访问店铺失败&am…...
Golang | Leetcode Golang题解之第326题3的幂
题目: 题解: func isPowerOfThree(n int) bool {return n > 0 && 1162261467%n 0 }...
人大金仓(Kingbase)数据库高阶函数详解
人大金仓(Kingbase)数据库高阶函数详解 人大金仓(Kingbase)数据库是一款基于 PostgreSQL 的国产关系型数据库(PostgreSQL 高阶函数详解:全面深入的功能与实用示例 ),提供了丰富的高阶函数,以支…...
云原生真机实验
基于Proxmox VE构建中小企业云计算平台 首先Proxmox VE是什么?能用来做什么? Proxmox VE是一个完整的企业虚拟化开源平台。借助内置的 Web 界面,可以在单个解决方案上轻松管理 VM(开虚拟机的) 和容器、软件定义的存储和网络、高可用性群集以…...
【电子电路学习笔记】——模电笔记
关于专栏:本专栏用于分享学习电子电路过程中记录的笔记。模电部分使用的教材是高等教育出版社,华成英主编的《模拟电子技术基础(第六版)》(其他版本的内容差不多,建议使用最新版教材)࿱…...
部署伪分布式 Hadoop集群
部署伪分布式 Hadoop集群 一、JDK安装配置1.1 下载JDK1.2 上传解压1.3 java环境配置 二、伪分布式 Hadoop 安装配置2.1 Hadoop 下载2.2 上传解压2.3 Hadoop 文件目录介绍2.4 Hadoop 配置2.4.1 修改 core-site.xml 配置文件2.4.2 修改 hdfs-site.xml 配置文件2.4.3 修改 hadoop-…...
十九、虚拟机VMware Workstation(CentOSDebian)的安装
目录 🌻🌻 一、安装 VMware Workstation1.1 安装 VMware Workstation1.2 虚拟机上安装 CentOS1.3 虚拟机安装 Debian 二、配置Debian方便第三方工具远程连接2.1 配置debian2.2 安装远程SSH工具并连接 一、安装 VMware Workstation 官网下载 本地资源库…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
基于鸿蒙(HarmonyOS5)的打车小程序
1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...
Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...
【深尚想】TPS54618CQRTERQ1汽车级同步降压转换器电源芯片全面解析
1. 元器件定义与技术特点 TPS54618CQRTERQ1 是德州仪器(TI)推出的一款 汽车级同步降压转换器(DC-DC开关稳压器),属于高性能电源管理芯片。核心特性包括: 输入电压范围:2.95V–6V,输…...
python打卡day49@浙大疏锦行
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 一、通道注意力模块复习 & CBAM实现 import torch import torch.nn as nnclass CBAM(nn.Module):def __init__…...
