当前位置: 首页 > news >正文

asm技术简介

概述

ASM是一个Java字节码操作和分析框架。它可以用于直接生成类或动态生成、修改已存在的类。ASM提供了一些核心组件和API,使得开发者可以在运行时创建或修改编译后的Java类。使用ASM技术,开发者可以实现如下功能:

  1. 动态生成类:在运行时根据特定的需求动态生成新的类。这对于某些需要根据用户输入或其他运行时数据动态定义行为的应用程序非常有用。

  2. 修改现有类:在不改变原有代码的情况下,修改已经编译好的类的行为。这可以用于增加日志、性能监控、安全检查等。

  3. 分析字节码:分析已编译的Java类的结构和内容,用于工具开发或性能优化等场景。

ASM通过提供低层次和高层次的API,使得操作字节码既灵活又方便。低层次API(如访问者模式)提供了对字节码的细粒度控制,而高层次API(如树API)则允许以更接近源代码的方式操作字节码。

ASM的核心组件

  • ClassReader:用于读取编译后的.class文件或者已加载的类的字节码数据。
  • ClassWriter:用于生成新的类或修改现有类的字节码。
  • ClassVisitor:一个接口,通过访问者模式来访问类的结构和字节码指令。
  • MethodVisitor:用于访问方法的字节码指令。

使用ASM的优点

  • 性能:ASM是一个性能非常优秀的库,它的设计允许以最小的内存和处理时间来操作字节码。
  • 灵活性:ASM提供了从低层次到高层次的API,使得开发者可以根据需要选择最合适的方式来操作字节码。
  • 成熟稳定:ASM已经被广泛应用于许多开源项目和商业产品中,经过了长时间的实践检验。

使用场景

  • 框架开发:很多Java框架,如Spring,Hibernate等,使用ASM来增强类的功能或生成代理类。
  • 性能监控:通过修改字节码插入监控代码,来收集运行时数据,用于性能分析。
  • 安全审计:分析或修改字节码来增强应用的安全性。

总之,ASM是一个强大的工具,它为Java字节码的操作和分析提供了广泛的支持。

示例

下面是一个使用ASM框架的简单示例,演示如何动态生成一个类。这个类将包含一个方法public int add(int a, int b),该方法返回两个整数的和。

首先,确保你的项目中已经添加了ASM的依赖。如果是使用Maven,可以在pom.xml中添加如下依赖:

<dependency><groupId>org.ow2.asm</groupId><artifactId>asm</artifactId><version>9.2</version> <!-- 请根据需要使用最新版本 -->
</dependency>

接下来是生成类的代码:

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;import java.lang.reflect.Method;public class AsmExample {public static void main(String[] args) throws Exception {// 创建ClassWriter对象,COMPUTE_MAXS表示自动计算栈帧大小和局部变量表大小ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);// 定义类的基本信息:Java版本、访问标志、类名、签名、父类、接口cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "ExampleClass", null, "java/lang/Object", null);// 创建构造函数MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);mv.visitVarInsn(Opcodes.ALOAD, 0);mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);mv.visitInsn(Opcodes.RETURN);mv.visitMaxs(1, 1);mv.visitEnd();// 创建add方法mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "add", "(II)I", null, null);mv.visitVarInsn(Opcodes.ILOAD, 1); // 加载第一个参数mv.visitVarInsn(Opcodes.ILOAD, 2); // 加载第二个参数mv.visitInsn(Opcodes.IADD); // 执行加法操作mv.visitInsn(Opcodes.IRETURN); // 返回操作mv.visitMaxs(2, 3); // 设置栈帧和局部变量表大小mv.visitEnd();// 完成类的定义cw.visitEnd();// 获取定义的类的字节码数组byte[] b = cw.toByteArray();// 使用自定义类加载器加载这个类MyClassLoader loader = new MyClassLoader();Class<?> exampleClass = loader.defineClass("ExampleClass", b);// 使用反射调用add方法Object obj = exampleClass.newInstance();Method addMethod = exampleClass.getMethod("add", int.class, int.class);Object result = addMethod.invoke(obj, 5, 3);System.out.println("5 + 3 = " + result);}static class MyClassLoader extends ClassLoader {public Class<?> defineClass(String name, byte[] b) {return super.defineClass(name, b, 0, b.length);}}
}

这个示例中,我们首先使用ClassWriter来定义一个新的类ExampleClass,然后为这个类添加了一个构造函数和一个add方法。add方法接收两个整数参数,返回它们的和。通过ClassWriter生成的字节码数组被自定义的类加载器MyClassLoader加载到JVM中。最后,我们通过反射创建了ExampleClass的实例,并调用了它的add方法。

这个例子展示了ASM在动态生成类和方法方面的强大能力。通过ASM,我们可以在运行时根据需要动态地生成和修改类,这在很多高级应用场景中非常有用,比如实现自定义的框架、代理、或者进行字节码级别的优化等。

AsmExample 生成的代码大致如下:(并不是真的生成代码)

public class ExampleClass {public ExampleClass() {super();}public int add(int a, int b) {return a + b;}
}

这个生成的类有以下特点:

  1. 类名为 ExampleClass
  2. 继承自 java.lang.Object
  3. 有一个无参构造函数
  4. 包含一个名为 add 的公共方法,接受两个 int 参数,返回它们的和

这个类是通过 ASM 字节码操作框架动态生成的,而不是通过编写 Java 源代码来创建的。ASM 允许我们在运行时生成和修改 Java 字节码,这在某些高级编程场景中非常有用,比如动态代理、代码生成等。

运行结果

5 + 3 = 8

相关文章:

  • 中国联通(海外)数据中心资源:从基础设施运维服务到IDC机房增值服务
  • 在 Qt 中构建和解析多层嵌套的 JSON 数据
  • 通信工程学习:什么是SISO单入单出
  • GEE问题: 离校后学校edu账户无法使用,如何导出我们所有的脚本
  • C#通用文档识别挂接示例、手写体识别接口
  • 昇思MindSpore进阶教程--报错分析
  • AJAX(简介以及一些用法)
  • (笔记)第三期书生·浦语大模型实战营(十一卷王场)--书生入门岛通关第1关Linux 基础知识
  • [RabbitMQ] 7种工作模式详细介绍
  • 一文上手SpringSecurity【七】
  • 怎么查看网站是否被谷歌收录,查看网站是否被搜索引擎收录5个方法与步骤
  • 傅里叶级数在机器人中的应用(动力学参数辨识)
  • Kotlin高阶函数func
  • 二值图像的面积求取的两种方法及MATLAB实现
  • 【漏洞复现】VEXUS多语言货币交易所存在未授权访问漏洞
  • .pyc 想到的一些问题
  • co.js - 让异步代码同步化
  • docker python 配置
  • js学习笔记
  • Selenium实战教程系列(二)---元素定位
  • Spark VS Hadoop:两大大数据分析系统深度解读
  • 初识MongoDB分片
  • 从0实现一个tiny react(三)生命周期
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 我从编程教室毕业
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • python最赚钱的4个方向,你最心动的是哪个?
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 翻译 | The Principles of OOD 面向对象设计原则
  • ![CDATA[ ]] 是什么东东
  • #android不同版本废弃api,新api。
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (function(){})()的分步解析
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (zt)最盛行的警世狂言(爆笑)
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (全注解开发)学习Spring-MVC的第三天
  • (图)IntelliTrace Tools 跟踪云端程序
  • .NET C# 配置 Options
  • .NET MAUI Sqlite数据库操作(二)异步初始化方法
  • .Net插件开发开源框架
  • .net和php怎么连接,php和apache之间如何连接
  • @param注解什么意思_9000字,通俗易懂的讲解下Java注解
  • [ C++ ] STL---仿函数与priority_queue
  • [AIGC] Redis基础命令集详细介绍
  • [Android] 240204批量生成联系人,短信,通话记录的APK
  • [Android]一个简单使用Handler做Timer的例子
  • [AX]AX2012 SSRS报表Drill through action
  • [C#][opencvsharp]opencvsharp sift和surf特征点匹配
  • [codevs1288] 埃及分数
  • [CSAWQual 2019]Web_Unagi ---不会编程的崽
  • [CSS] 点击事件触发的动画
  • [C语言][C++][时间复杂度详解分析]二分查找——杨氏矩阵查找数字详解!!!