Java动态编程之Instrumentation

Instrumentation 介绍与使用 使用 Insrumentation ,开发者而言构建一个独立于应用程序的代理程序(Agent),检车和协助运行在JVM 上的程序,甚至可以替换和修改某些类的定义。简单的来说 开发者使用Instrumentation 可以实现一种虚拟机级别的AOP实现。 Instrumentation 的最大作用,就是类定义动态改变和操作。 程序运行时,通过 -javaagent 参数指定一个特定的 ... 阅读详情

需求

在不修改代码重新发布的情况下,查看一个线上正运行代码的方法的入参、返回值,或者增加某些日志的打印

解决方案

arthas
btrace
自定义classloader,发现需要动态加载的类定义变更时对类进行重新加载打破双亲委派
本文暂不讨论自定义classloader方式,工具的具体使用方法可以查看官方文档,那么这些工具的底层是如何实现的呢?没错他们底层都使用了JDK提供的Instrumentation接口。那么Instrumentation接口如何使用呢?

用法

以下内容为翻译的该接口的javadoc 该类提供测试Java编程语言代码所需的服务。Instrumentation是将字节码添加至方法中为收集工具所使用的数据。因为改变是纯添加动作,这些工具不会改变应用状态或行为。像这样良性的工具案例包含监控代理agents,profilers,coverage analyzers, and event loggers. 获取该接口实例的方法有两种:

当JVM通过显示的指定一个代理类的方式运行。在这种情形下,Instrumentation实例通过代理类的premain方法传入
JVM提供一个机制在JVM运行之后启动代理。在这种情形下,Instrumentation实例通过代理代码的agentmain方法传入

显示指定代理类方式获取

案例代码取自arthas pom配置为生成的manifest文件中指定premain代码提供类以及代理类提供类

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>single</goal>
            </goals>
            <phase>package</phase>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <archive>
                    <manifestEntries>
                        <Premain-Class>com.taobao.arthas.agent.AgentBootstrap</Premain-Class>
                        <Agent-Class>com.taobao.arthas.agent.AgentBootstrap</Agent-Class>
                        <Can-Redefine-Classes>true</Can-Redefine-Classes>
                        <Can-Retransform-Classes>true</Can-Retransform-Classes>
                        <Specification-Title>${project.name}</Specification-Title>
                        <Specification-Version>${project.version}</Specification-Version>
                        <Implementation-Title>${project.name}</Implementation-Title>
                        <Implementation-Version>${project.version}</Implementation-Version>
                    </manifestEntries>
                </archive>
            </configuration>
        </execution>
    </executions>
</plugin>

代理类、premain方法提供类编写接收Instrumentation实例的方法

// 通过-agent方法显示指定方式启动JVM时会回调该方法传入Instrumentation实例
public static void premain(String args, Instrumentation inst) {
    main(args, inst);
}

将premain提供类打成jar包。启动其他jvm时将该该jar作为agent参数出入即可,启动命令如下:

java -javaagent "${HOME}/.arthas/lib/3.1.0/arthas/arthas-agent.jar" ...

JVM启动后再启动代理方式获取

同上中方式相同,maven的pom配置为生成的manifest文件中指定agent代码提供类 代理类方法提供类编写接收Instrumentation实例的方法

// JVM启动后,通过VM.attach方式附加至目标JVM时回调该方法传入Instrumentation
public static void agentmain(String args, Instrumentation inst) {
    main(args, inst);
}

将代理类附加到目标JVM

private void attachAgent(Configure configure) throws Exception {
    // 根据PID获取目标JVM描述实例
    VirtualMachineDescriptor virtualMachineDescriptor = null;
    for (VirtualMachineDescriptor descriptor : VirtualMachine.list()) {
        String pid = descriptor.id();
        if (pid.equals(Integer.toString(configure.getJavaPid()))) {
            virtualMachineDescriptor = descriptor;
        }
    }
    VirtualMachine virtualMachine = null;
    try {
        // 通过pid方式直接依附至目标JVM
        if (null == virtualMachineDescriptor) { // 使用 attach(String pid) 这种方式
            virtualMachine = VirtualMachine.attach("" + configure.getJavaPid());
        } else {
            // 通过JVM描述符方式依附
            virtualMachine = VirtualMachine.attach(virtualMachineDescriptor);
        }
    ...
        // 为依附上的目标JVM加载代理jar
        virtualMachine.loadAgent(arthasAgentPath,
                configure.getArthasCore() + ";" + configure.toString());
    ...
}

通过Instrumentation转换类字节码
实现ClassFileTransformer接口的transform方法

@Override
public byte[] transform(final ClassLoader inClassLoader, String className, Class<?> classBeingRedefined,            ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        ...
        // inClassLoader:将要被转换类所在的类加载器,如果是bootstrap loader则该参数为null
        // className:将要被转换类的全限定名称
        // classBeingRedefined:将要被转换类的class
        // protectionDomain:将要被转换类的保护域
        // classfileBuffer:将要被转换类的字节码
        // 修改增强后的字节码
        return enhanceClassByteArray;
        ...
}

将ClassFileTransformer实现添加至Instrumentation,并执行转换

// Enhancer为arthas中提供的ClassFileTransformer实现类
final Enhancer enhancer = new Enhancer(adviceId, isTracing, skipJDKTrace, enhanceClassSet, methodNameMatcher, affect);
// 将转换类添加至Instrumentation
inst.addTransformer(enhancer, true);
...
// 执行转换
inst.retransformClasses(clazz);

总结

instrumentation.addTransformer的第二个参数canRetransform如果不指定默认为false,如果为true,则在显示调用retransformClasses时会立即回调。
jdk api文档中指明在转换类定义之前已经实例化的对象不会受影响,这种说法指的应该是因为对象不能新增、删除、更改字段方法等,所以类型的实例不会受到重定义的影响;但是对于方法的修改会生效,官方也有说明:已经入栈的方法不会受影响,但是对于下一次方法调用则会使用新的定义
ClassFileTransformer实例中要对类名称进行匹配,因为其他类加载时也可能会走到该转换类中导致出现异常,例如:

###### start transform
loader:sun.misc.Launcher$AppClassLoader@18b4aac2, className:null, classBeingRedefined:null
###### end transform
C/C++基础讲解(四十三)之图形篇之绘制直线、圆、圆弧、 椭圆 程序主要是基于Visual studio 2019进行编译完成了,有兴趣的小伙伴可以自己安装下Visual studio 2019,网上有现成的教程,当然了,如果有问题,也可以和我联系,这里我们主要讲解些源码实例,不多说了,言归正传。 C语言,做为学习其他语言的基础语言,其重要性就不言而喻了.下面我将和大家一起来学习探讨C语言的相关奥秘。 实例1:绘制直线 实例2:绘制圆 实例2:绘制圆弧 实例2:绘制椭圆 阅读详情

相关推荐

FPGA赋能:从加权灰度均值到快速收敛的自动曝光实战

本文深入探讨了FPGA在工业视觉自动曝光算法中的应用,重点介绍了加权灰度均值法的优化实现与快速收敛策略。通过硬件友好的算法改造和流水线架构设计,FPGA方案能在1帧内完成曝光调整,显著提升处理速度和能效比,适用于复杂光照条件下的工业检测场景。

weixin_29306317的博客 82

JAVA Instrumentation

什么是Instrumentation? java Instrumentation指的是可以用独立于应用程序之外的代理(agent)程序来监测和协助运行在JVM上的应用程序。这种监测和协助包括但不限于获取JVM运行时状态,替换和修改类定义等。 Java SE5中使用JVM TI替代了JVM PI和JVM DI。提供一套代理机制,支持独立于JVM应用程序之外的程序以代理的方式连接和访问JVM。java.lang.instrument是在JVM TI的基础上提供的Java版本的实现。 Instrumentatio

通往神秘的道路的专栏 4084

用ESP32-S3+OV2640摄像头+ILI9488屏,DIY一个能联网的智能猫眼(附完整代码)

本文详细介绍了如何利用ESP32-S3微控制器搭配OV2640摄像头和ILI9488显示屏,DIY一个功能强大的智能猫眼系统。从硬件选型、电路设计到软件开发,提供了完整的解决方案和优化技巧,包括图像采集显示、WiFi远程访问及低功耗设计,适合智能家居爱好者动手实践。

weixin_30897233的博客 501

一篇文章带你揭开 Java Instrumentation 的原理

文章目录一、前言二、热部署初识三、Java Instrumentation四、Java Instrumentation 静态代码示例五、Java Agent 示例 —— attach的使用 一、前言 日常开发中避免不了,修改了代码重新启动应用去验证问题,如果没有热部署,则需要每次修改完就去编译代码再启动,这样子的操作看似简单, 但很耗时,特别电脑配置不高,或者项目比较大的情况 二、热部署初识 热部署其实就是在代码运行时去加载我们动态现在修改过的代码到服务器上,诸如 SpringBoot的devtools插

啊狸的Java的博客 2162

新华硕笔记本ubuntu18.04双系统安装之后,wifi没有显示无法链接wifi

本来我以为跟简单安装一个wifi网卡的驱动就可以解决的问题,没想到花了我一早上的时候解决… 惭愧。 另外,本来是没打算写这篇博客的,但是我在搜索解决这个问题的过程中, 发现多人提出的解决方案跟我的都不一样,甚至我的解决方案都没有搜到相应的答案,还是只能靠自己啊。。 言归正传,还是说说怎么正确的安装wifi驱动吧! 1. wifi没有正确安装、或没有正确配置的表现 我的电脑现象: 有wifi图标, wifi设置上显示unaviable,无法搜索到任何wifi; 还有其他类似的表现,大家可以看看其他朋友的提

Ian的博客 1889

VL53L0X加盖玻片后精度暴跌?手把手教你完成串扰校准(CrossTalk Calibration)

本文详细解析了VL53L0X激光测距传感器加盖玻片后精度下降的原因,并提供了串扰校准(CrossTalk Calibration)的完整解决方案。通过分步指导和实用代码示例,帮助工程师恢复毫米级测距精度,适用于智能门锁、扫地机器人等应用场景。

weixin_33708432的博客 539

字节码进阶之java Instrumentation原理详解

Java Instrumentation是Java API的一部分,它允许开发人员在运行时修改类的字节码。使用此功能,可以实现许多高级操作,例如性能监控、代码覆盖率分析等。通过Java提供的Instrumentation接口,我们能够在运行时改变和监控Java程序,这种能力在许多场景中都非常有用,比如性能调优、故障排查、代码覆盖率分析等。然而,Instrumentation接口的使用和字节码操作本身都是高级主题,需要深入理解JVM和字节码的工作原理。

日拱一卒无有尽,功不唐捐终入海 2280

在hyper-v管理器中修改WSL虚拟交换机后,打开wsl闪退

此次是因为修改了WSL虚拟交换机造成的wsl打不开或闪退,还有一种可能是关闭了hyper-v造成了wsl。

DN金猿的博客 1170

Maven JaCoCo进行代码覆盖率分析

通过在Maven项目中集成JaCoCo,开发者可以自动化地生成详细的代码覆盖率报告,并且可以设置覆盖率门槛以确保代码质量。JaCoCo不仅有助于提高代码的测试覆盖率,还促进了更高质量代码的编写。希望本文能帮助你成功地在Maven项目中集成JaCoCo,并有效地使用它来提升你的软件开发流程。

HaSaKing的博客 2355

goahead(嵌入式Web服务器)之文件传输篇

goahead文件上传原理: 使用html form即表单提交文件上传请求,web服务器核心处理接收客户端Post过来的文件数据(注意post的是二进制数据),最后,web服务器把接收到文件数据以二进制格式写到服务器本端存储系统。 goahead文件上传步骤: 1、创建upload.html文件,内容如下: <html> <head> <meta charset="utf-8"/> <title>Upload</title> </head&g

weixin_40732273的博客 3495

Midscene.js(1):Chrome 插件实战之基于 AI 驱动 WEB UI 自动化测试「喂饭教程」

Midscene.js 是一款开源的AI驱动UI自动化工具,支持自然语言交互、数据提取、断言验证等多种功能。自然语言交互。本文将以 Midscene.js Chrome 插件为例,带你从零上手,体验如何用最简单的方式实现高效、智能的UI自动化测试。

blues_C的博客 4404

Java编程的动态特性, 从Reflection到Runtime Class Transformation

关于Java编程的动态特性,从认识的过程上要从 Reflection 到 instrumentation。1. 初步的开发者刚接触到Reflection会非常兴奋,因为反射可以在运行时完成很多之前不可能的任务,这件利器使人打破了很多束缚。2. Java Annotation出现后,更让Java变得更加有活力,更加友好。Annotation + Reflection + enum + Class...

barryzhong 428

YOLOv11的物理信息神经网络(PINN):引入物理规律约束目标运动预测

本文介绍了YOLOv11目标检测与PINN物理信息神经网络的融合技术。YOLOv11采用增强特征提取和参数优化架构,在保持实时性的同时提升检测精度。PINN通过将物理方程嵌入损失函数,实现数据高效学习。两者的结合可显著提升运动预测准确性和遮挡处理鲁棒性。文章详细阐述了环境配置、YOLOv11模型验证方法,并提供了基础PINN框架代码实现,展示了物理约束如何通过自动微分整合到神经网络中。该融合技术适用于自动驾驶、无人机导航等需要物理规律建模的视觉感知场景。

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 422

java动态编程简述

1.使用Compiler Api 创建类文件

beijing20120926的专栏 1032

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

instrumentation 功能介绍(javaagent)

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34112030的博客 462

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

AOP、动态代理、CGlib(原理实践)

Java 代理模式实现方式,主要有如下五种方法: 1. 静态代理,工程师编辑代理类代码,实现代理模式;在编译期就生成了代理类。 2. 基于 JDK 实现动态代理,通过jdk提供的工具方法Proxy.newProxyInstance动态构建全新的代理类(继承Proxy类,并持有InvocationHandler接口引用 )字节码文件并实例化对象返回。(jdk动态代理是由java内部的反射机制来实...

bug_remover的博客 355

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Java AOP的实现机制

申明:本文转载:http://www.iteye.com/topic/1116696 1 AOP各种的实现 AOP就是面向切面编程,我们可以从几个层面来实现AOP。 在编译器修改源代码,在运行期字节码加载前修改字节码或字节码加载后动态创建代理类的字节码,以下是各种实现机制的比较。    类别 机制 原理 优点 缺点

spring_shower的专栏 574

AOP各种的实现

附件中有本文的源代码和Pdf版。本文写的很长的原因,是不希望大家学习AOP时到处找资料,大家有时间可以按照本文动手实践下,相信会有非常大的收获的,有什么问题互相交流,有问必答! 1 AOP各种的实现 AOP就是面向切面编程,我们可以从几个层面来实现AOP。 在编译器修改源代码,在运行期字节码加载前修改字节码或字节码加载后动态创建代理类的字节码,以下是各种实现机制的比较。

For that dream 660

<span class=“js_title_inner“>手把手教你实现一个Java Agent</span>

Arthas命令很多,如果是exit、logout、quit、jobs、fg、bg、kill等简单的命令,就会直接执行,如果是trace这种复杂的命令,会专门用一个类写处理的逻辑,如上图,根据名字就可以猜到这个类是处理什么命令的,这么多类的组织形式是模版模式,入口在com.taobao.arthas.core.shell.command.AnnotatedCommand。以上是我写的小demo,有很多不足之处,看看大佬是怎么写的,arthas的trace命令可以统计方法耗时,如下图。

芋艿V 40

java aop框架_关于介绍几个JAVA的AOP框架开源项目的问题?

哈士奇WWW基于Java的简单、动态、轻量级、强大的AOP框架。既强大又简单,有助于更容易的集成AOP到新的或已存在的项目中。AspectWerkz 主要特性:1. 运行时和加载时字节码修正:你可以在运行时或编译时轻松的改造任何(旧)应用程序或除了rt.jar以外的外部类库2. 支持join point模型3. 支持Annotation:匹配JavaDoc和JSR-175,支持用户自定义Anno...

weixin_34006342的博客 271

AOP的实现机制

http://www.iteye.com/topic/1116696 1 AOP各种的实现 AOP就是面向切面编程,我们可以从几个层面来实现AOP。 在编译器修改源代码,在运行期字节码加载前修改字节码或字节码加载后动态创建代理类的字节码,以下是各种实现机制的比较。    类别 机制 原理 优点 缺点 静态A

气自华 297

AOP的实现机制[讲解一]

附件中有本文的源代码和Pdf版。本文写的很长的原因,是不希望大家学习AOP时到处找资料,大家有时间可以按照本文动手实践下,相信会有非常大的收获的,有什么问题互相交流,有问必答! 1 AOP各种的实现 AOP就是面向切面编程,我们可以从几个层面来实现AOP。 在编译器修改源代码,在运行期字节码加载前修改字节码或字节码加载后动态创建代理类的字节码,以下是各种实现机制的比较。   

Joepher的专栏 406
上一篇: Java中泛型——类型擦除
下一篇: 分析Java 8中 Objects 类源码
Java_ttcd
博客等级 码龄4年 198粉丝 190原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值