IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 使用ASM实现简单的热部署-简单记录 -> 正文阅读

[Java知识库]使用ASM实现简单的热部署-简单记录

字节码增强技术?

ASM

  ASM是对java字节码操纵框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class?文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。ASM从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。asm字节码增强技术主要是用来反射的时候提升性能的,如果单纯用jdk的反射调用,性能是非常低下的,而使用字节码增强技术后反射调用的时间已经基本可以与直接调用相当了。

spring 的Aop中使用的cglib的底层原理便是asm。

ASM采用的是责任链模式:

图17 ASM修改字节码

ASM Core API可以类比解析XML文件中的SAX方式,不需要把这个类的整个结构读取进来,就可以用流式的方法来处理字节码文件。好处是非常节约内存,但是编程难度较大。然而出于性能考虑,一般情况下编程都使用Core API。在Core API中有以下几个关键类:

  • ClassReader:用于读取已经编译好的.class文件。
  • ClassWriter:用于重新构建编译后的类,如修改类名、属性以及方法,也可以生成新的类的字节码文件。
  • 各种Visitor类:如上所述,CoreAPI根据字节码从上到下依次处理,对于字节码文件中不同的区域有不同的Visitor,比如用于访问方法的MethodVisitor、用于访问类变量的FieldVisitor、用于访问注解的AnnotationVisitor等。为了实现AOP,重点要使用的是MethodVisitor。

使用的场景有很多,我们这里只讲一个动态替换class文件的方法。?

我们这里的使用场景:热部署

用我们公司的项目来说:项目为多个策略配置类替换,使用自定义类加载器加载的每个策略,然后反射生成一个个单例配置策略对象放在map中。策略数量有限。

因为线上的配置类会在线更换,还需要重新动态修改方法逻辑等,自己定义AOP功能,操作且要求项目不能随意重启。所以只能热部署的方式来加载要修改的class,自己定义了一个类加载器他继承了双亲委派机制,因为还有个父类要用apploader加载,因为一个类加载器多次,报类加载异常。所以,我想到了使用热部署的方式,更换策略对象。?

因为我们线上使用的是一个单例的策略类,把当前类替换即可(ps:这里也有另一种方式:java agent)

1,更新class类名这样类加载不会报错,实现热部署。

2,实现不依托spring实现的 自定义框架AOP .

1,引用jar 包

	    <!-- https://mvnrepository.com/artifact/org.ow2.asm/asm -->
		<dependency>
			<groupId>org.ow2.asm</groupId>
			<artifactId>asm</artifactId>
			<version>9.1</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm-commons -->
		<dependency>
			<groupId>org.ow2.asm</groupId>
			<artifactId>asm-commons</artifactId>
			<version>9.1</version>
		</dependency>

2,使用ASM

(1):重命名class

原class?

public class HelloAsm   {

    private int aa;
    private static String b = "123";
    private static final String c = "abc";
    private static HashMap hashMap = new HashMap();

    public void test2() {
        int aa = this.aa;
        hashMap.put("22", "11");
        System.out.println("Hello ASM :" + c);
    }


    @Override
    public void test() {
        System.out.println(">>>>>>>>> 我是测试 ");
    }

新class?


public class GoodAsm {
    private int aa;
    private static String b = "123";
    private static final String c = "abc";
    private static HashMap hashMap = new HashMap();

    public GoodChild1() {
    }

    public void test2() {
        int var1 = this.aa;
        hashMap.put("22", "11");
        System.out.println("Hello ASM :abc");
    }

    public void test() {
        System.out.println(">>>>>>>>> 我是测试  ");
    }
}
  public static void main(String[] args) throws Exception {
        String old_name = "com/my/asm/HelloWorld";
        String old_name_path = "F:\\davinqi\\target\\classes\\com\\my\\asm\\HelloWorld.class";
        String new_name = "com/my/asm/GoodChild1";
        InputStream fileInputStream = new FileInputStream( new File(old_name_path ));

        // 读class对象
        ClassReader cr = new ClassReader(fileInputStream);

        // 构建Class写对象
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        // ClassVisitor
        Remapper remapper = new SimpleRemapper(old_name , new_name );
        ClassVisitor cv = new ClassRemapper(cw, remapper);、
        cr.accept(cv,  ClassReader.SKIP_DEBUG);

        // 生成新Class
        byte[] bytes2 = cw.toByteArray();
        FileOutputStream fos = new FileOutputStream("F:\\davinqi\\src\\main\\java\\com\\my\\asm\\GoodChild1.class");
        fos.write(bytes2);
        fos.close();
    }

执行完成后在指定路径下生成的class文件,我们就可用使用此类加载到jvm 反射生成实例对象。

F:\davinqi\src\main\java\com\my\asm\GoodAsm.class:?

(2):重命名方法名

?TODO?

(3):方法修改增强

(4):字段修改

图片以及部分描述引用:

??https://tech.meituan.com/2019/09/05/java-bytecode-enhancement.html

本文只是简单记录下,如果有错误希望大家能指正。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章           查看所有文章
加:2021-07-14 10:44:42  更:2021-07-14 10:45:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/18 17:07:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码