崩溃了!我说用attach进行问题定位,面试官问我原理

Arthas(阿尔萨斯)是一款开源的Java诊断和监控工具,可以在生产环境中进行实时的应用程序分析和故障排查。Arthas的实现原理主要基于Java Instrumentation API和Java Agent技术。

Java Agent 是 Java 编程语言提供的一种特殊机制,允许你在程序运行过程中对字节码进行转换和增强。它是通过 Java 的 Instrumentation API 来实现的,可以用于在应用程序加载类时进行监测、修改和增强。Java Agent 通常被用于实现性能监测、代码分析、方法耗时统计、字节码增强等功能。

Java Agent 的主要特点

  1. 动态性: Java Agent 允许你在程序运行时加载代理类,对类进行转换和增强,从而实现动态修改已编译类的功能。

  2. 无侵入性: 使用 Java Agent 不需要修改源代码,也不需要重新编译。这使得你可以在不改变程序结构的情况下,实现一些横切关注点的逻辑。

  3. 全局性: Java Agent 可以在整个 JVM 中生效,对加载的所有类都可以进行转换和增强。这使得你可以监测、分析和增强全局的应用行为。

Java Agent 的使用步骤

开发 Java Agent 的涉及的要点如下图所示:

图片

image.png

要使用 Java Agent,通常需要遵循以下步骤:

  1. 创建代理类: 创建一个代理类,实现 java.lang.instrument.Instrumentation 接口的 premain 方法。

  2. 注册代理类: 在代理类的 premain 方法中注册代理类。这将使代理类在 JVM 启动时加载并执行。

  3. 定义转换规则: 在代理类中,你可以使用 Instrumentation API 来定义转换规则,即如何对类的字节码进行转换。

示例:方法计时器 Java Agent

以下是一个简单的 Java Agent 示例,实现对所有方法的计时统计:

import java.lang.instrument.Instrumentation;public class MethodTimerAgent {public static void premain(String agentArgs, Instrumentation instrumentation) {System.out.println("Agent premain called");instrumentation.addTransformer(new MethodTimerTransformer());}
}

增加创建一个 ClassFileTransformer 接口的实现类 MethodTimerTransformer

public class MethodTimerTransformer implements ClassFileTransformer {  private final static String prefix = "\nlong startTime = System.currentTimeMillis();\n";  private final static String postfix = "\nlong endTime = System.currentTimeMillis();\n";  // 被处理的方法列表  final static Map<String, List<String>> methodMap = new HashMap<String, List<String>>();  public MethodTimerTransformer() {  add("com.example.TimeTest.sayHello");  }  private void add(String methodString) {  String className = methodString.substring(0, methodString.lastIndexOf("."));  String methodName = methodString.substring(methodString.lastIndexOf(".") + 1);  List<String> list = methodMap.get(className);  if (list == null) {  list = new ArrayList<String>();  methodMap.put(className, list);  }  list.add(methodName);  }  @Override  public byte[] transform(  ClassLoader loader,  String className,  Class<?> classBeingRedefined,  ProtectionDomain protectionDomain,  byte[] classfileBuffer) throws IllegalClassFormatException {  if (className.startsWith("com/example/")) {  className = className.replace("/", ".");  System.out.println("Transforming class: " + className);  // 在方法前后添加计时逻辑  CtClass ctclass = null;  try {  ctclass = ClassPool.getDefault().get(className);// 使用全称,用于取得字节码类<使用javassist>  System.out.println(ctclass.getName());  for (String methodName : methodMap.get(className)) {  System.out.println(methodName);  String outputStr = "\nSystem.out.println(\"this method " + methodName  + " cost:\" +(endTime - startTime) +\"ms.\");";  CtMethod ctmethod = ctclass.getDeclaredMethod(methodName);// 得到这方法实例  String newMethodName = methodName + "$old";// 新定义一个方法叫做比如sayHello$old  ctmethod.setName(newMethodName);// 将原来的方法名字修改  // 创建新的方法,复制原来的方法,名字为原来的名字  CtMethod newMethod = CtNewMethod.copy(ctmethod, methodName, ctclass, null);  // 构建新的方法体  StringBuilder bodyStr = new StringBuilder();  bodyStr.append("{");  bodyStr.append(prefix);  bodyStr.append(newMethodName + "($$);\n");// 调用原有代码,类似于method();($$)表示所有的参数  bodyStr.append(postfix);  bodyStr.append(outputStr);  bodyStr.append("}");  newMethod.setBody(bodyStr.toString());// 替换新方法  ctclass.addMethod(newMethod);// 增加新方法  }  return ctclass.toBytecode();  } catch (Exception e) {  System.out.println(e.getMessage());  e.printStackTrace();  }  }  return classfileBuffer;  }  
}

在上述示例中,MethodTimerAgent 是 Java Agent 的代理类,通过 premain 方法注册了 MethodTimerTransformer 类。MethodTimerTransformer 是转换器类,实现了 ClassFileTransformer 接口,允许你在 transform 方法中修改目标类的字节码。

这里的对字节码的修改用到了javassistjavassist介绍可以参考字节码增强技术-Javassist

想要其他项目使用,我们还需完成以下几步:

创建文件resources/META-INF/MANIFEST.MF,内容如下:

Manifest-Version: 1.0  
Can-Redefine-Classes: true  
Can-Retransform-Classes: true  
Premain-Class: com.example.MethodTimerAgent  
Boot-Class-Path: javassist-3.28.0-GA.jar

pom文件增加下面配置

<build>  <plugins>  <plugin>  <groupId>org.apache.maven.plugins</groupId>  <artifactId>maven-jar-plugin</artifactId>  <version>2.4</version>  <configuration>  <archive>  <!-- 就是把前面的配置的MANIFEST.MF打入jar中,以指定premain的位置,否则会报:  Failed to find Premain-Class manifest attribute in  -->  <manifestFile>${maven.configuration.manifestFile}</manifestFile>  </archive>  </configuration>  </plugin>  </plugins>  
</build>

使用 Java Agent

我们新建一个项目,增加一个测试类:

public class TimeTest {  public static void main(String[] args) {  sayHello();  }  public static void sayHello() {  try {  Thread.sleep(2000);  System.out.println("hello world!!");  } catch (InterruptedException e) {  e.printStackTrace();  }  }  
}

要使用 Java Agent,你需要将代理类打包成 JAR 文件,并在启动 JVM 时使用 -javaagent 参数指定该 JAR 文件的路径。例如:

java -javaagent:path/to/agent.jar -jar your-application.jar

我们这里直接在idea上测试:

增加VM Options参数

图片


由于我们使用到了javassist,需要javassist的jar与java-agent的jar放在一起

图片

最后我们运行我们的测试类TimeTest,结果如下:

图片

 

可以看到方法执行耗时被打印出来了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/638447.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3.php开发-个人博客项目输入输出类留言板访问IPUA头来源

目录 知识点 : 输入输出 配置环境时&#xff1a; 搜索框&#xff1a; 留言板&#xff1a; 留言板的显示&#xff08;html&#xff09;&#xff1a; php代码显示提交的留言&#xff1a; 写入数据库 对留言内容进行显示&#xff1a; php全局变量-$_SERVER 检测来源 墨…

AMEYA360:航顺HK32AUTO39A—适用车载娱乐系统优化方案

车载娱乐系统&#xff0c;顾名思义最开始其功能主要是为驾驶员和乘客提供娱乐体验&#xff0c;但现在智能座舱时代到来&#xff0c;车载信息娱乐系统已成为“人-车-环境”交互的重要载体&#xff0c;是除了驾驶以外的其他任务的中心。 从功能模块上看&#xff0c;车载娱乐系统从…

【算法练习Day50】下一个更大元素II接雨水

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 下一个更大元素II接雨水单调…

9.4 Lambda表达式

9.4 Lambda表达式 1 Lambda语法2. 基于Lambda实现函数式编程3. Stream流式处理 1 Lambda语法 2. 基于Lambda实现函数式编程 3. Stream流式处理

【网站项目】基于SSM的273校园二手交易网站

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

cesium实现动态围栏

项目中使用到了cesium,需要实现动态的围栏的效果&#xff0c; 在网上也找了好多案例&#xff0c;通过着色器来实现效果&#xff0c;为此也有好多博主也附上了自己的代码&#xff0c;也许是因为使用方法不同&#xff0c;复制代码并修改依旧还是没有通过他们的方式实现效果【着色…

STM32标准库开发——PWM驱动代码

PWM驱动初始化代码 使能定时器二时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);设置定时器时钟源 TIM_InternalClockConfig(TIM2);配置定时器二的时基单元 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_TimeBaseInitStruct.TIM_ClockDivisionTIM_CKD_D…

vmware 安装Rocky-9.3系统

安装系统截图 安装完成&#xff0c;启动 查看版本和内核 开启远程登陆授权 1、编辑配置文件 #提升权限&#xff0c;输入su,并输入密码 su #编辑ssh文件开启root远程登陆 vi /etc/ssh/sshd_config找到以下内容&#xff1a;#PermitRootLogin prohibit-password 添加&#xff1a…

C语言——小细节和小知识11

一、自幂数 1、介绍 自幂数&#xff0c;也被称为阿姆斯特朗数&#xff0c;是一种特殊类型的数&#xff0c;在数学上具有一个有趣的性质&#xff1a;一个 n 位的正整数&#xff0c;其各个位上的数字的 n 次幂之和等于它本身。 这里是自幂数的定义步骤&#xff1a; 确定位数 (…

Windows ssh登录eNSP交换机

目录 1. Cloud IO配置1.1 创建UDP端口1.2 创建本地连接1.3 端口映射设置 2. 交换机配置2.1 配置vlanif2.2 配置vty2.3 配置ssh用户2.4 配置aaa2.5 使用Xshell工具登录2.6 用户和密码2.7 登录成功 3. 使用cmd 登录报错提示3.1 手动指定加密算法&#xff0c;提示密码长度无效3.2 …

Softmax函数介绍

Softmax函数是一种常用的激活函数&#xff0c;用于将一组实数值转换为概率分布。它常用于多类别分类问题中&#xff0c;将输入向量映射为各个类别的概率。 Softmax函数的公式如下&#xff1a; 其中&#xff0c;示输入向量的第 &#xfffd;i 个元素&#xff0c;&#xfffd;n …

【JVM】JVM概述

JVM概述 基本介绍 JVM&#xff1a;全称 Java Virtual Machine&#xff0c;即 Java 虚拟机&#xff0c;一种规范&#xff0c;本身是一个虚拟计算机&#xff0c;直接和操作系统进行交互&#xff0c;与硬件不直接交互&#xff0c;而操作系统可以帮我们完成和硬件进行交互的工作特…

红队渗透靶机:TOPPO: 1

目录 信息收集 1、arp 2、nmap 3、nikto 4、whatweb 5、dirsearch WEB tips1 tips2 SSH登录 提权 系统信息收集 本地 信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:69:c7:bf, IPv4: 192.168.110…

Linux第33步_TF-A移植的第1步_创建新的设备树

TF-A移植第1步就是创建新的设备树&#xff0c;并命名为“stm32mp157d-atk”。 和“TF-A移植”有关的知识点&#xff1a; 1)设备树英文名字叫做Device tree&#xff0c;用来描述板子硬件信息的&#xff0c;比如开发板上的 CPU有几个核 、每个CPU核主频是多少&#xff0c;IIC、…

单元测试、模块测试、web接口测试

单元测试与模块测试 什么是“单元测试”、“模块测试”&#xff1f; 然而在功能的实现代码中并没有“单元”&#xff0c;也没有“模块”&#xff1b;只有函数、类和方法。先来分别看看它们 的定义&#xff1a; 单元测试&#xff08;Unit testing&#xff09;&#xff0c;是指…

代码随想录算法训练营第三天 | 链表理论基础 203.移除链表元素 707.设计链表 206.反转链表

链表理论基础 链表是一种通过指针串连在一起的线性结构&#xff0c;每一个节点由两部分组成&#xff0c;一个是数据域&#xff0c;一个是指针域&#xff08;存放指向下一个节点的指针&#xff09;。最后一个节点的指针指向 null。链表的存储方式&#xff1a;数组在内存中是连续…

带POE网络变压器与2.5G/5G/10G网络变压器产品特点介绍

Hqst华轩盛(石门盈盛)电子导读&#xff1a;一起来了解带POE网络变压器与2.5G/5G/10G网络变压器产品特点&#xff1f; 一﹑带POE网络变压器与2.5G/5G/10G网络变压器产品特点介绍 首先、POE网络变压器产品与常规不带POE产品的区别&#xff1a; 带POE网络变压器主要要求是耐电流等…

(二)CarPlay集成开发之苹果的iAP协议

文章目录 概要协议格式鉴权流程CarPlay中的iAP2协议应用小结 概要 iAP2协议是由苹果公司定义的一种数据通信协议&#xff0c;主要用于苹果设备认证外设&#xff0c;以及与外设数据交换的一种协议 协议格式 协议格式一共分为三种类型&#xff0c;分别为握手包&#xff0c;链路…

42.接雨水 - 力扣(LeetCode)

问题描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。输入格式 height [0,1,0,2,1,0,1,3,2,1,2,1]输出格式 6解释 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图&#xff0c;在这种情况下…

「优选算法刷题」:查找总价格为目标值的两个商品

一、题目 购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况&#xff0c;返回任一结果即可。 示例 1&#xff1a; 输入&#xff1a;price [3, 9, 12, 15], target 18 输出&#xff1a;[3,15] 或者 [15,3]示例…