Java动态字节码注入技术

Java ASM 框架:字节码操作的常见用法(生成类,修改类,方法插桩,方法注入) 前言 ASM是一款读写Java字节码的工具,可以达到跳过源码编写,编译,直接以字节码的形式创建类,修改已经存在类(或者jar中的class)的属性,方法等。 通常用来开发一些Java开发的辅助框架,其做法是在你编写的Java代码中注入一些特定代码(俗称字节码插装)达到特定目的,以Android开发为例最常用的方法通过字节码插装实现热修复,事件监听,埋点,开源框架等非常规操作,当然在Android开发中通常辅以Gradle插件一起使用,这个改天在写。 背景 早就听说过ASM和字节码插桩技术,但是工... 阅读详情
AI摘要

本文介绍了Java动态字节码注入技术,包括其定义、过程,以及如何通过ASM框架进行示例操作。同时,对比了与即时编译和JavaAgent的关系,指出其在AOP和代码增强中的应用。

一、什么是Java动态字节码注入技术

        Java动态字节码注入技术是一种在运行时修改Java字节码的技术。它允许开发者在程序运行期间动态地向现有的Java类中注入字节码,并改变类的行为和功能。这项技术通常用于实现AOP(面向切面编程)、代码增强、动态代理等需求。

二、Java动态字节码注入的过程

        Java动态字节码注入的过程一般包括以下步骤:

  1. 获取需要修改的目标类的字节码,可以通过ClassLoader动态加载目标类或读取已经存在的类文件。
  2. 使用字节码操作库(如ASM、ByteBuddy等)来生成新的字节码。
  3. 插入新的字节码到目标类的方法中,可以修改方法的逻辑、添加新的方法、插入调用等操作。
  4. 将修改后的字节码重新加载到JVM中,使得程序在运行时使用新的字节码。

三、代码示例

        创建了一个自定义的 MyClassLoader 类,继承自 ClassLoader。该自定义类加载器重写了 defineClassFromBytecode 方法,用于通过 defineClass 方法加载字节码并定义类。然后,我们可以使用自定义类加载器的实例调用 defineClassFromBytecode 方法,传入类名和字节码,得到加载后的 Class 对象。最后,我们可以使用反射机制创建该类的对象实例。

public class MyClassLoader extends ClassLoader {
    public Class<?> defineClassFromBytecode(String className, byte[] bytecode) {
        return defineClass(className, bytecode, 0, bytecode.length);
    }
}

        需要注意的是,defineClass 方法将字节码转换为一个新的 Class 对象,并将其添加到当前的类加载器的命名空间中。在加载字节码时,会根据字节码的内容生成一个新的类。 

        再定义一个目标类和要执行的方法:

public class TargetClass {
    public void add(int a, int b) {
        int result = a + b;
        System.out.println("Result: " + result);
    }
}

        下面是一个简单的示例使用ASM框架进行动态字节码注入,将目标类的add方法的实现替换为打印"Hello, World!"的代码: 

package com.xxx.xxx;

import org.objectweb.asm.*;

public class BytecodeInjector {
    public static void main(String[] args) throws Exception {
        // 读取目标类的字节码
        ClassReader reader = new ClassReader(TargetClass.class.getName());

        // 创建 ClassWriter,并指定生成的字节码版本
        ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        // 创建自定义的 ClassVisitor,生成新的字节码
        ClassVisitor visitor = new ClassVisitor(Opcodes.ASM7, writer) {
            @Override
            public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
                if (name.equals("add")) {
                    MethodVisitor mv = cv.visitMethod(access, name, descriptor, signature, exceptions);

                    // 创建新的方法实现
                    MethodVisitor newMv = new MethodVisitor(Opcodes.ASM7, mv) {
                        @Override
                        public void visitCode() {
                            super.visitCode();

                            // 向方法中插入指令
                            mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
                            mv.visitLdcInsn("Hello, World!");
                            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
                        }
                    };

                    return newMv;
                }

                return super.visitMethod(access, name, descriptor, signature, exceptions);
            }
        };

        // 开始访问目标类,并触发自定义的 ClassVisitor 生成新的字节码
        reader.accept(visitor, ClassReader.EXPAND_FRAMES);

        // 获取生成的字节码
        byte[] modifiedClass = writer.toByteArray();

        // 使用自定义的类加载器加载修改后的字节码
        MyClassLoader loader = new MyClassLoader();
        Class<?> modifiedClassObj = loader.defineClassFromBytecode(TargetClass.class.getName(), modifiedClass);

        // 创建目标类的实例并调用修改后的方法
        TargetClass target = (TargetClass) modifiedClassObj.getDeclaredConstructor().newInstance();
        target.add(2, 3);
    }
}

        运行示例代码后,会输出 "Hello, World!" 而不是原本的相加结果。这个简单的示例展示了使用ASM框架进行动态字节码注入的过程,并修改了目标类的行为。

代码讲解

visitMethod 方法是 ClassVisitor 类的一个方法,用于访问类中的方法。它有以下参数:

  • access:表示方法的修饰符和属性,使用 ASM 的 Opcodes 类中定义的常量来表示,如 Opcodes.ACC_PUBLIC、Opcodes.ACC_PRIVATE、Opcodes.ACC_STATIC 等。
  • name:表示方法的名称,字符串类型。
  • descriptor:表示方法的描述符,也可以看作方法的签名。它使用一种特殊的字符串格式来描述方法的参数类型和返回类型,如 (Ljava/lang/String;I)V 表示一个接受一个字符串和一个整型参数,并且没有返回值的方法。
  • signature:表示泛型信息的签名,如果方法不是泛型方法,则为 null。
  • exceptions:表示方法可能抛出的异常类型,以字符串数组形式表示异常的全限定名。

        visitMethod 方法可以根据需要进行重写,用于在访问方法时执行自定义操作。在重写的方法体内,可以使用 cv.visitMethod 创建或修改方法,并返回一个 MethodVisitor 对象来进一步访问方法的字节码。

        例如,在上述示例中的 BytecodeInjector 类的 visitMethod 方法中,我们判断了当前访问的方法是否为目标方法 add,如果是,则创建了一个新的 MethodVisitor 对象,并在其中插入了打印 "Hello, World!" 的字节码指令。通过这种方式,我们在目标方法的字节码中进行了修改,实现了自定义功能。

        需要注意的是,这里介绍的 visitMethod 方法是 ClassVisitor 类中的方法,与 MethodVisitor 类中的 visitMethod 不同。ClassVisitor 类的 visitMethod 主要用于访问类的方法,而 MethodVisitor 类的 visitMethod 则用于访问方法内部的字节码指令。

四、Java动态字节码注入技术和即时编译的区别

Java动态字节码注入技术和即时编译是两个不同的概念。

        Java动态字节码注入技术是一种在运行时修改Java字节码的技术,它允许开发者通过程序修改已经加载到JVM中的类的字节码,以改变类的行为和功能。这种技术通常用于实现AOP(面向切面编程)、代码增强、动态代理等需求。例如,在一些框架和工具中,利用字节码注入技术可以在方法执行前后插入额外的逻辑,实现日志记录、性能监控等功能。

        即时编译(Just-In-Time Compilation,JIT)是Java虚拟机(JVM)的一项重要特性。JIT编译器在程序运行过程中将字节码即时编译成本地机器码,以提高程序的执行效率。JIT编译器会根据代码的运行情况对热点代码进行动态编译,将其转换为本地机器码后再执行,从而加速程序的运行。这种即时编译技术在Java性能优化中扮演着重要的角色。

        虽然Java动态字节码注入技术和即时编译都涉及到对字节码的处理,但它们的目的和应用场景不同。字节码注入是为了在运行时修改已加载类的行为和功能,而即时编译是为了提高程序的执行效率。两者可以结合使用,实现更强大和灵活的Java程序功能和性能优化。

五、Java Agent 和字节码注入技术关系

        Java Agent 是通过 JVM 的 Instrumentation API 实现的一种机制,允许在运行时修改或监测已加载类的字节码。它可以用于各种目的,包括代码注入、性能监控、调试工具等。Java Agent 通过实现 Instrumentation API 中的 ClassFileTransformer 接口来拦截和修改正在加载的类的字节码。

        字节码注入技术是 Java Agent 的一种应用场景,指的是在运行时将自定义的字节码注入到已加载的类中,以实现动态修改类的行为。通过字节码注入技术,可以实现 AOP(面向切面编程)、动态代理、代码增强等功能。字节码注入通常涉及使用字节码操作库(如 ASM、Byte Buddy 或 Javassist)来读取、修改和生成字节码的过程。

        因此,可以认为 Java Agent 是一种更广义的概念,而字节码注入是 Java Agent 的一种具体应用方式之一。Java Agent 可以用于其他目的,例如性能监控、安全检查等,而字节码注入技术更专注于在运行时动态修改已加载类的字节码以达到特定的目的。

JVM——JavaAgent与字节码注入 阅读详情

相关推荐

字节码增强技术之 Java Agent 入门

前言 分布式链路追踪中为了获取服务之间调用链信息,采集器通常需要在方法的前后做埋点。在 Java 生态中,常见的埋点方式有两种: 依赖 SDK 手动埋点; 利用 Java Agent 技术来做无侵入埋点。 我们所熟知的分布式监控系统,是 Zipkin 开始的,最经典的是搞懂 X-B3 Ttrace 协议,使用 Brave SDK,手动埋点生成 Trace。但是 SDK 埋点的方式,对业务代码存在侵入性,当升级埋点时,必须要做代码的变更。 那么如何和业务逻辑解绑呢? Java 还提供了另外一种方式:

m0_69305074的博客 848

【8】JVM-字节码技术

目录 知识点1:应用场景 知识点2:字节技术优势 知识点3:常见的字节码操作类库 1、BCEL 2、ASM 3、CGLB 4、javassist (1)Javassist优势 (2)avassist的局限性 (3)使用Javassist创建类 (4)使用Javassist修改类文件信息 知识点1:应用场景 AOP技术、Lombok去除重复代码插件、动态修改class文件等...

19年的努力,并不是说说而已! 12万+

Java 动态字节码技术编程

在Java编程中,动态字节码技术是一项强大而灵活的特性,它允许开发人员在运行时修改和生成字节码。这种能力为我们提供了很多有趣的用例,例如在运行时创建动态代理、AOP(面向切面编程)和字节码增强等。通过反射,我们可以获取类的字节码对象,并对其进行操作。通过动态字节码技术,我们可以在运行时修改和生成字节码,从而实现一些灵活的编程需求。生成字节码后,我们将其写入文件,并使用自定义的类加载器加载增强后的类。下面我们将探讨两个常见的使用动态字节码技术的场景:动态代理和字节码增强。在上面的示例中,我们定义了一个。

YabClass的博客 254

字节码注入/字节码注入原理java-零开始网络安全详细教程

本文正在参加「金石计划 . 瓜分6万现金大奖」前言突然想起来之前讲SQL注入时忘记讲一下这个宽字节注入了,因为这个知识点还是挺重要的

程序员三九的博客 560

STM32独立实现CANOpen主机功能:从零构建轻量级控制方案

本文详细介绍了如何在STM32上不依赖CanFestival库,从零构建一个轻量级的CANOpen主机方案。文章深入剖析了CANOpen主机的三大核心功能——NMT网络管理、SDO参数配置与PDO过程数据交换,并提供了从硬件准备、驱动层构建到协议实现的完整代码实战。该方案代码精简,资源占用低,特别适合在资源受限的STM32平台上实现工业控制、电机驱动等场景的稳定通信。

potato的博客 1072

【蓝牙专题】HCI协议解析

一、概念: 很多人接触蓝牙,是从HCI开始,因为HCI是主机控制接口协议(Host Controller Interface),蓝牙命令通过HCI来发送到Controller; 1、架构 如下图,HCI通过物理接口(USB、UART等)或虚拟接口,传递数据到Controller,Controller也通过同样的接口发送接收数据,这里注意到HCI层是在L2CAP层之下,LMP层之上; HCI

蚂蚁的专栏 5069

ByteKit:Java字节码增强的利器

ByteKit:Java字节码增强的利器 项目介绍 ByteKit 是由阿里巴巴开源的一款专为 Java 字节码增强而设计的工具。它旨在提供一套简洁、高效的 API,使得开发人员能够轻松地进行字节码增强操作。ByteKit 不仅继承了 Arthas 中字节码增强的优秀特性,还进一步简化了操作流程,使得即使是非专业的开发人员也能快速上手。 项目技术分析 ByteKit 基于 ASM 框架,提供了一系...

gitblog_00968的博客 1003

NIST随机性测试实战:从理论公式到结果解读

本文详细解析了NIST随机性测试的实战应用,从基础测试到高级测试,涵盖频数测试、块频数测试、游程测试等核心方法。通过实际案例和参数设置经验,帮助读者理解如何解读测试结果并排查常见问题,提升随机数生成质量。文章还分享了自动化测试流程和硬件RNG特殊处理技巧,适合密码学和区块链开发者参考。

weixin_29323365的博客 314

Java字节码

Java最黑科技的玩法就是字节码编程,也就是动态修改或是动态生成 Java 字节码。使用字节码可以玩出很多高级的玩法,最高级的还是在 Java 程序运行时进行字节码修改和代码注入。听起来是不是一些很黑客,也很黑科技的事?是的,这个方式使用 Java 这门静态语言在运行时可以进行各种动态的代码修改,而且可以进行无侵入的编程。 比如,我们不需要在代码中埋点做统计或监控,可以使用这种技术把我们的监控代码...

螃蟹士兵 1万+

MATLAB算法实战应用案例精讲-【数模应用】梯度提升决策树(GDBT)(附python代码)

GBDT(Gradient Boosting Decision Tree) 又叫 MART(Multiple Additive Regression Tree),是一种迭代的决策树算法,该算法由多棵决策树组成,它在被提出之初就和SVM一起被认为是泛化能力(generalization)较强的算法。近些年更因为被用于搜索排序的机器学习模型而引起大家关注。.........

qq_36130719的博客 2078

【深度学习新浪潮】智能体在图像处理领域的技术突破与实践指南

智能体正在重构图像处理的技术版图:从多智能体分工的"专业化协作",到多模态统一的"极简架构",再到工具增强的"实战能力",技术突破不断降低开发门槛并拓展应用边界。对于开发者而言,2025年的核心机遇在于结合具体场景选择成熟框架(如医疗用IteR-MRL、工业用NVIDIA NIM),通过微调与工具集成快速落地解决方案。随着硬件成本下降与开源生态完善,图像处理智能体将从当前的"高端场景赋能"走向"千行百业普及",真正成为数字世界的"视觉感知与操作核心"。

专注:太空算力、AI infra、异构调度、大模型成本工程 439

Java字节码技术(二)字节码增强之ASM、JavaAssist、Agent、Instrumentation

文章目录前言从AOP说起静态代理动态代理JavaProxyCGLIB字节码增强实现AOPASMJavaAssist运行时类加载Instrumentation接口JavaAgentPremainClass随JVM进程启动AgentClass以Attach方法注入Agent总结 前言 在上篇文章Java字节码技术(一)中已经介绍了Java中字节码相关的基础概念。我们知道,Java代码转换后的JVM指令...

hosaos的博客 1万+

YOLOv13添加DRB模块map暴涨12.33!准确率提升8.56!召回率提升15.66

本文介绍了在YOLOv13模型中添加DRB模块的改进方法。实验结果显示,添加DRB模块后模型性能显著提升,mAP暴涨12.33%,准确率提升8.56%。文章详细说明了移植过程,包括创建yolov13-DRB.yaml配置文件、修改tasks.py和__init__.py文件,以及引入UniRepLKNet模块的具体实现。其中重点描述了GRNwithNHWC、NCHWtoNHWC等核心组件的实现细节,并提供了完整的模型结构配置代码。这些改进使得YOLOv13模型在保持原有架构优势的同时,获得了更强大的特征提取

FJN110的博客 2819

修改jar 注入_基于Java Agent实现字节码注入

目录探针JavaAgent原理概述与示例基于JavaAgent实现动态修改代码基于JavaAgent实现字节码注入基于JavaAgent实现内存Webshell注入基于JavaAgent实现内存Webshell检测程序目标注入自定义Java代码,实现JVM内存和GC监控(搜了下,其实很多APM都会使用字节码注入的方式)项目代码使用IDEA新建一个maven项目,项目结构如下:m...

weixin_39790504的博客 326

MTK Meta ISP 工具使用技巧与参数读取路径全解析

在联发科(MediaTek, MTK)平台上进行相机图像调试时,Meta ISP 工具是连接 PC 与设备进行参数调整、寄存器读取和图像输出的重要工具。本文以实战角度出发,系统梳理 Meta ISP 的使用流程、关键模块功能、典型调试技巧与参数读取路径,结合最新版平台(如MTK Genio/Dimensity 系列)架构,帮助工程师掌握联发科图像调优的核心流程。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 1148

96.在 Vue 3 中使用 OpenLayers 探究加载 Point、Polygon 的极限

在前端 GIS(地理信息系统)开发中,OpenLayers 作为一个功能强大的 Web 地图库,广泛用于加载地图、渲染矢量数据(点、线、面)、叠加图层等场景。然而,当涉及到。

小彭的博客 1155

Java低代码引擎如何实现“拖拽即编译”?:深度解析AST动态解析、字节码注入与运行时沙箱三大关键技术

揭秘Java低代码平台内核开发教程核心:实现“拖拽即编译”关键路径。深入剖析AST动态解析、字节码注入与运行时沙箱三大技术,支撑可视化配置实时生成可执行逻辑,兼顾性能与安全。适用于企业级低代码引擎研发,值得收藏。

ByteGlow的博客 179

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

「JAVA基础探针技术」Java探针-Java Agent技术

我们利用javaAgent和ASM字节码技术,在JVM加载class二进制文件的时候,利用ASM动态的修改加载的class文件,在监控的方法前后添加计时器功能,用于计算监控方法耗时,同时将方法耗时及内部调用情况放入处理器,处理器利用栈先进后出的特点对方法调用先后顺序做处理,当一个请求处理结束后,将耗时方法轨迹和入参map输出到文件中,然后根据map中相应参数或耗时方法轨迹中的关键代码区分出我们要抓取的耗时业务。2、支持抓取特定的代码配置,方便对配置的特定方法进行抓取,过滤出关系的代码执行耗时情况。

z1ztai的博客 813

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

字节码增强技术:从ASM到底层Agent的原理与实践

摘要:字节码增强技术通过修改Java字节码实现非侵入式功能扩展,主要包括ASM和JavaAgent两大方案。ASM作为底层框架直接操作JVM指令,适合精细控制但学习成本高;JavaAgent通过Instrumentation API在类加载时注入逻辑,支持动态Attach但性能略低。两者各有优劣:ASM适用于代码生成和静态分析,JavaAgent更适合APM监控和热部署。高层框架如ByteBuddy在ASM基础上提供更友好API。技术选型需根据场景权衡性能、动态性和技术门槛,共同构成Java生态强大的扩展能

huahua8088的博客 866

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

一文学会 Java 动态编译

Java动态编译技术可以让我们在程序运行时动态地生成和加载Java代码,从而实现更加灵活和高效的应用程序。本文介绍了Java动态编译的基本概念、实现方法和相关案例。如果你对Java动态编译技术感兴趣,可以通过阅读的官方文档,进一步了解该技术的实现细节。同时,需要注意的是,Java动态编译技术虽然可以提供更高的灵活性和可扩展性,但在实际使用时也存在一些安全隐患。因为动态编译可以在程序运行时生成和加载代码,如果不加以限制和控制,可能会导致恶意代码的注入和执行。

Java是世界上最好的语言 3433

Java Agent 字节码增强技术

Java Agent 是一种特殊的 Java 程序,它可以在 JVM 启动时或运行时加载,用于修改或监控其他 Java 应用程序的字节码。try {");

fujiedada的专栏 419

使用Btrace来动态监控方法的参数和返回值

btrace简介: btrace是一种动态跟踪分析一个运行中的Java应用程序的工具,它基于java的探针技术动态地向目标应用程序的字节码注入追踪代码(字节码追踪),这些追踪字节码追踪代码使用Java语言表达,也就是BTrace的脚本 btrace在github上的地址: https://github.com/btraceio/btrace 编译好的软件包的下载地址: https://github...

weixin_30396699的博客 279

手把手教你Java字节码Demo

手把手教你Java字节码Demo 接触中间件的开发来说,了解像Pinpoint(https://github.com/naver/pinpoint)、BTrace(https://github.com/btraceio/btrace)、阿里的JVM-SANDBOX(https://github.com/alibaba/jvm-sandbox)、Java在线问题诊断工具Greys(https://github.com/oldmanpushcart/greys-anatomy)等,都是通过字节码技术,无侵入的干

黄老师的博客 596

【每天学习一点点:字节码增强】class字节码结构、ASM生成新的class字节码、javassist操作字节码、Instrument类库运行时加载类、Agent注入到JVM、JPDA接口attach

Javassist 提供了一组 API 来访问和操作 Java 类的属性、方法、构造函数等元素,并提供了丰富的模板功能来简化 Java 类的创建和修改过程。这样就需要利用到class字节码的javap -c中的code区域的指令集,也就是说我们方法在运行的时候,会被编译成指令进行操作,因此我们可以修改对应的指令来改变行为。我们都知道java是一个跨平台的开发语言,其主要核心在于class字节码,也就是java在编译后会生成对应的class字节码文件,会通过类加载器将class字节码加载到jvm运行空间中。

路漫漫其修远兮 吾将上下而求索 811

Java Memshell Generator源码深度剖析:注入器生成原理

Java Memshell Generator是一款功能强大的Java内存马生成工具,支持自定义配置,能够针对不同中间件框架生成对应的内存马注入器。本文将深入剖析其注入器生成的核心原理,帮助开发者理解内存马注入的实现机制。 ## 注入器生成的核心架构 注入器生成是Java Memshell Generator的核心功能,主要由`InjectorGenerator`类负责协调。该类位于`jmg-

gitblog_00072的博客 438
上一篇: Python程序设计——元组、集合和字典
下一篇: Java Agent 技术:动态修改字节码
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值