深入了解Java ClassLoader、Bytecode 、ASM、cglib (I)

Java字节码操作指南:ASM核心原理与实战应用 Java字节码是Java虚拟机(JVM)执行的核心中间表示,它作为Java源代码与机器指令之间的桥梁,是实现'一次编写,到处运行'的关键。字节码操作技术允许开发者在运行时动态修改或生成类文件,突破Java语言层面的限制,为框架开发、性能监控和代码增强提供了底层支持。其技术价值在于能够实现AOP、动态代理、热部署等高级特性,广泛应用于性能监控工具、APM系统和各类开发框架中。本文以ASM这一高性能字节码操作库为例,深入解析其事件驱动的访问者模式设计,并通过方法注入、动态类生成等实战案例,展示如何利用字节码技术 阅读详情

一、Java ClassLoader

1,什么是ClassLoader
与 C 或 C++ 编写的程序不同,Java 程序并不是一个可执行文件,而是由许多独立的类文件组成,每一个文件对应于一个 Java 类。
此外,这些类文件并非立即全部都装入内存,而是根据程序需要装入内存。ClassLoader 是 JVM 中将类装入内存的那部分。
而且,Java ClassLoader 就是用 Java 语言编写的。这意味着创建您自己的 ClassLoader 非常容易,不必了解 JVM 的微小细节。

2,一些重要的方法
A)loadClass
ClassLoader.loadClass() 是ClassLoader的入口点。该方法的定义为:Class loadClass( String name, boolean resolve );
name:JVM 需要的类的名称,如 Foo 或 java.lang.Object。
resolve:参数告诉方法是否需要解析类。

B)defineClass
defineClass方法是ClassLoader的主要诀窍。该方法接受由原始字节组成的数组并把它转换成Class对象。

C)findSystemClass
findSystemClass方法从本地文件系统中寻找类文件,如果存在,就使用defineClass将原始字节转换成Class对象,以将该文件转换成类。

D)resolveClass
可以不完全地(不带解析)装入类,也可以完全地(带解析)装入类。当编写我们自己的loadClass时可以调用resolveClass,这取决于loadClass的resolve参数的值。

E)findLoadedClass
findLoadedClass充当一个缓存:当请求loadClass装入类时,它调用该方法来查看ClassLoader是否已装入这个类,这样可以避免重新装入已存在类所造成的麻烦。

3,Java2中ClassLoader的变动
1)loadClass的缺省实现
在Java2中loadClass的实现嵌入了大多数查找类的一般方法,并使您通过覆盖findClass方法来定制它,在适当的时候findClass会调用loadClass。
这种方式的好处是可能不一定要覆盖loadClass,只要覆盖findClass就行了,这减少了工作量。

2)新方法:findClass
loadClass的缺省实现调用这个新方法。

3)新方法:getSystemClassLoader
如果覆盖findClass或loadClass,getSystemClassLoader让我们以实际ClassLoader对象来访问系统ClassLoader,而不是固定的从findSystemClass 调用它。

4)新方法:getParent
为了将类请求委托给父ClassLoader,这个新方法允许ClassLoader获取它的父ClassLoader。

4,定制ClassLoader
其实我们或多或少都使用过定制的ClassLoader,因为Applet查看器中就包含一个定制的ClassLoader。
它不在本地文件系统中寻找类,而是访问远程服务器上的 Web 站点,经过 HTTP 装入原始的字节码文件,并把它们转换成JVM 内的类。
Applet查看器中的ClassLoader还可以做其它事情:它们支持安全性以及使不同的Applet在不同的页面上运行而互不干扰。
我们将写一个自己的ClassLoader实现示例,它将实现如下步骤,这也是ClassLoader的工作原理:
# 调用 findLoadedClass 来查看是否存在已装入的类。
# 如果没有,那么采用那种特殊的神奇方式来获取原始字节。
# 如果已有原始字节,调用defineClass将它们转换成Class对象。
# 如果没有原始字节,然后调用findSystemClass查看是否从本地文件系统获取类。
# 如果resolve参数是true,那么调用resolveClass解析Class对象。
# 如果还没有类,返回ClassNotFoundException。
# 否则,将类返回给调用程序。
话不多说,看看代码先:
FileClassLoader.java:

代码
  1. import java.io.ByteArrayOutputStream;   
  2. import java.io.File;   
  3. import java.io.FileInputStream;   
  4. import java.io.IOException;   
  5.   
  6. public class FileClassLoader extends ClassLoader {   
  7.   public Class findClass(String name) {   
  8.     byte[] data = loadClassData(name);   
  9.     return defineClass(name, data, 0, data.length);   
  10.    }   
  11.      
  12.   private byte[] loadClassData(String name) {   
  13.      FileInputStream fis = null;   
  14.     byte[] data = null;   
  15.     try {   
  16.        fis = new FileInputStream(new File("D://project//test//" + name + ".class"));   
  17.        ByteArrayOutputStream baos = new ByteArrayOutputStream();   
  18.       int ch = 0;   
  19.       while ((ch = fis.read()) != -1) {   
  20.          baos.write(ch);   
  21.        }   
  22.        data = baos.toByteArray();   
  23.      } catch (IOException e) {   
  24.        e.printStackTrace();   
  25.      }   
  26.     return data;   
  27.    }   
  28. }   

MyApp.java:
代码
  1. public class MyApp {   
  2.   public static void main(String[] args) throws Exception {   
  3.      FileClassLoader loader = new FileClassLoader();   
  4.      Class objClass = loader.findClass("MyApp");   
  5.      Object obj = objClass.newInstance();   
  6.      System.out.println(objClass.getName());   
  7.      System.out.println(objClass.getClassLoader());   
  8.      System.out.println(obj);   
  9.    }   
  10. }   

编译并运行MyApp类,结果为:
代码
  1. MyApp   
  2. FileClassLoader@757aef  
  3. MyApp@9cab16  

二、Bytecode

1,什么是Bytecode
C/C++编译器把源代码编译成汇编代码,Java编译器把Java源代码编译成字节码bytecode。
Java跨平台其实就是基于相同的bytecode规范做不同平台的虚拟机,我们的Java程序编译成bytecode后就可以在不同平台跑了。
.net框架有IL(intermediate language),汇编是C/C++程序的中间表达方式,而bytecode可以说是Java平台的中间语言。
了解Java字节码知识对debugging、performance tuning以及做一些高级语言扩展或框架很有帮助。

2,使用javap生成Bytecode
JDK自带的javap.exe文件可以反汇编Bytecode,让我们看个例子:
Test.java:

代码
  1. public class Test {   
  2.   public static void main(String[] args) {   
  3.     int i = 10000;   
  4.      System.out.println("Hello Bytecode! Number = " + i);   
  5.    }   
  6. }   

编译后的Test.class:
代码
  1. 漱壕   1 +   
  2.       
  3.   
  4.   
  5.   
  6.   
  7. <init> ()V Code LineNumberTable main ([Ljava/lang/String;)V   
  8. SourceFile     Test.java   
  9.    ! " java/lang/StringBuilder Hello Bytecode! Number = # $ # % & ' ( ) * Test java/lang/Object java/lang/System out Ljava/io/PrintStream; append -(Ljava/lang/String;)Ljava/lang/StringBuilder; (I)Ljava/lang/StringBuilder; toString ()Ljava/lang/String; java/io/PrintStream println (Ljava/lang/String;)V !   
  10.         
  11.         *                      >     ' < Y                      

使用javap -c Test > Test.bytecode生成的Test.bytecode:
代码
  1. Compiled from "Test.java"  
  2. public class Test extends java.lang.Object{   
  3. public Test();   
  4.    Code:   
  5.    0:   aload_0   
  6.    1:   invokespecial   #1; //Method java/lang/Object."<init>":()V   
  7.    4:  return  
  8.   
  9. public static void main(java.lang.String[]);   
  10.    Code:   
  11.    0:   sipush  10000  
  12.    3:   istore_1   
  13.    4:   getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;   
  14.    7:  new   #3; //class java/lang/StringBuilder   
  15.    10:   dup   
  16.    11:   invokespecial   #4; //Method java/lang/StringBuilder."<init>":()V   
  17.    14:   ldc   #5; //String Hello Bytecode! Number =   
  18.    16:   invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;   
  19.    19:   iload_1   
  20.    20:   invokevirtual   #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;   
  21.    23:   invokevirtual   #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;   
  22.    26:   invokevirtual   #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V   
  23.    29:  return  
  24.   
  25. }   


JVM就是一个基于stack的机器,每个thread拥有一个存储着一些frames的JVM stack,每次调用一个方法时生成一个frame。
一个frame包括一个local variables数组(本地变量表),一个Operand LIFO stack和运行时常量池的一个引用。

简单分析一下生成的字节码指令:
aload和iload指令的“a”前缀和“i”分别表示对象引用和int类型,其他还有“b”表示byte,“c”表示char,“d”表示double等等
我们这里的aload_0表示将把local variable table中index 0的值push到Operand stack,iload_1类似
invokespecial表示初始化对象,return表示返回
sipush表示把10000这个int值push到Operand stack
getstatic表示取静态域
invokevirtual表示调用一些实例方法
这些指令又称为opcode,Java一直以来只有约202個Opcode,具体请参考Java Bytecode规范。

我们看到Test.class文件不全是二进制的指令,有些是我们可以识别的字符,这是因为有些包名、类名和常量字符串没有编译成二进制Bytecode指令。

3,体验字节码增强的魔力
我们J2EE常用的Hibernate、Spring都用到了动态字节码修改来改变类的行为。
让我们通过看看ASM的org.objectweb.asm.MethodWriter类的部分方法来理解ASM是如何修改字节码的:

代码
  1. class MethodWriter implements MethodVisitor {   
  2.   
  3.     private ByteVector code = new ByteVector();   
  4.   
  5.     public void visitIntInsn(final int opcode, final int operand) {   
  6.         // Label currentBlock = this.currentBlock;   
  7.         if (currentBlock != null) {   
  8.             if (compute == FRAMES) {   
  9.                  currentBlock.frame.execute(opcode, operand, null, null);   
  10.              } else if (opcode != Opcodes.NEWARRAY) {   
  11.                 // updates current and max stack sizes only for NEWARRAY   
  12.                 // (stack size variation = 0 for BIPUSH or SIPUSH)   
  13.                 int size = stackSize + 1;   
  14.                 if (size > maxStackSize) {   
  15.                      maxStackSize = size;   
  16.                  }   
  17.                  stackSize = size;   
  18.              }   
  19.          }   
  20.         // adds the instruction to the bytecode of the method   
  21.         if (opcode == Opcodes.SIPUSH) {   
  22.              code.put12(opcode, operand);   
  23.          } else { // BIPUSH or NEWARRAY   
  24.              code.put11(opcode, operand);   
  25.          }   
  26.      }   
  27.   
  28.     public void visitMethodInsn(   
  29.         final int opcode,   
  30.         final String owner,   
  31.         final String name,   
  32.         final String desc)   
  33.      {   
  34.         boolean itf = opcode == Opcodes.INVOKEINTERFACE;   
  35.          Item i = cw.newMethodItem(owner, name, desc, itf);   
  36.         int argSize = i.intVal;   
  37.         // Label currentBlock = this.currentBlock;   
  38.         if (currentBlock != null) {   
  39.             if (compute == FRAMES) {   
  40.                  currentBlock.frame.execute(opcode, 0, cw, i);   
  41.              } else {   
  42.                 /*
  43.                   * computes the stack size variation. In order not to recompute
  44.                   * several times this variation for the same Item, we use the
  45.                   * intVal field of this item to store this variation, once it
  46.                   * has been computed. More precisely this intVal field stores
  47.                   * the sizes of the arguments and of the return value
  48.                   * corresponding to desc.
  49.                   */  
  50.                 if (argSize == 0) {   
  51.                     // the above sizes have not been computed yet,   
  52.                     // so we compute them...   
  53.                      argSize = getArgumentsAndReturnSizes(desc);   
  54.                     // ... and we save them in order   
  55.                     // not to recompute them in the future   
  56.                      i.intVal = argSize;   
  57.                  }   
  58.                 int size;   
  59.                 if (opcode == Opcodes.INVOKESTATIC) {   
  60.                      size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;   
  61.                  } else {   
  62.                      size = stackSize - (argSize >> 2) + (argSize & 0x03);   
  63.                  }   
  64.                 // updates current and max stack sizes   
  65.                 if (size > maxStackSize) {   
  66.                      maxStackSize = size;   
  67.                  }   
  68.                  stackSize = size;   
  69.              }   
  70.          }   
  71.         // adds the instruction to the bytecode of the method   
  72.         if (itf) {   
  73.             if (argSize == 0) {   
  74.                  argSize = getArgumentsAndReturnSizes(desc);   
  75.                  i.intVal = argSize;   
  76.              }   
  77.              code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0);   
  78.          } else {   
  79.              code.put12(opcode, i.index);   
  80.          }   
  81.      }   
  82. }   

通过注释我们可以大概理解visitIntInsn和visitMethodInsn方法的意思。
比如visitIntInsn先计算stack的size,然后根据opcode来判断是SIPUSH指令还是BIPUSH or NEWARRAY指令,并相应的调用字节码修改相关的方法。

本文引自http://hi.baidu.com/maoshenmusic/blog/item/5e65dc2419baa6044c088d1a.html

Java Classloading Mechanism : ClassLoader & ASM & 动态字节码增强 NULL 博文链接:https://wuaner.iteye.com/blog/1011036 立即下载

相关推荐

Transformer在CV里太耗算力?手把手拆解Restormer的MDTA与GDFN模块

本文深度解析了CVPR2022最佳论文提名作品Restormer的创新模块MDTA与GDFN,有效解决了Transformer在计算机视觉领域的高计算复杂度问题。通过通道注意力降维和门控前馈网络设计,Restormer在图像恢复重建任务中显著降低计算量,同时保持高性能,为实时图像处理提供了可行方案。

weixin_30258901的博客 445

cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_mod

使用 Visual Studio Code(简称“VS Code”) 开发 vue 项目时,控制台出现以下报错信息,cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_mod

YHLSunshine的博客 3339

fastjson1.2.83反序列化漏洞

【代码】fastjson1.2.83反序列化漏洞。

Coder的博客 1万+

字节码实践 -- 使用 ASM 实现 AOP

       ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。ASM 从类文件中读入信息后,能...

上善若水,水善利万物而不争。 3397

评分卡建模学习(一)————数据预处理part.3

目录六、数据处理的思路及代码(一)对缺失值的处理:在我这个数据预处理的part.1板块(二)对异常值的处理:在我这个数据预处理的part.2板块(三)数据归一化、标准化:在我这个数据预处理的part.2板块(四)非结构化数据转变+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++———————————————————————————————————————————++++++++++++++++++++++++++

Morven_dai的博客 898

从零开始学习信号完整性(SIPI)--1 简介

信号完整性就是研究如何让驱动芯片发出的信号经过传输通道被接收芯片正确接收的学问。 信号完整性包含了三个要素: 信号:是被传输的主体,我们首先要了解、熟悉信号的特性。 芯片:分为驱动芯片和接收芯片,信号完整性工程师就是要实现信号在驱动芯片和接收芯片之间的正确传输。 传输通道:是传输信号的介质,是信号所走的“路”。如何实现信号的正确传输呢?那就要信号完整性工程师为信号“修路”、“搭桥”。

qq_29476769的博客 4万+

jvm 一之 类加载器

自定义一个类加载器加载指定磁盘的class文件}}}@Overridetry{//从磁盘中读取到一个class文件网络向服务器端发送rest请求拿到class文件//如何读取class文件class文件如何组成}}/***从文件中读取去class文件**///采用NIO读取break;}}}}//使用该自定义类加载器加载class//读取class加载到内存中Class...

ws - 兮的博客空间 777

Matlab实现POD本征正交分解数据降维模型

近年来,随着大数据时代的到来,各种复杂的工程问题产生了海量的高维数据,如何有效降维、提取数据中的关键信息成为了众多领域中的重要问题。在传统的数据降维方法中,PCTFA(主成分分析)是一种典型的统计方法,然而对于流体动力学等非线性问题,PCTFA在处理时可能失去部分物理意义,难以捕捉到系统的复杂性。在降维过程中,POD提取的主要特征通常是一组复杂的正交基函数,如何将这些结果有效地转化为直观且易于理解的物理意义,特别是在实际应用中,对该特征的理解和分析,依然是一个重要的课题。本项目的扩展性也得到了有效体现。

优质创作者: 人工智能技术领域 对于有一定基础的 MATLAB和Python带具体需求都可以详谈 MATLAB和Python可以提供代码调试服务加油 谢谢 你的鼓励是我前行的动力 谢谢支持 加油 谢谢 1216

深入了解Java ClassLoader,Bytecode,ASM,Cglib

一、Java ClassLoader1,什么是ClassLoader 与 C 或 C++ 编写的程序不同,Java 程序并不是一个可执行文件,而是由许多独立的类文件组成,每一个文件对应于一个 Java 类。 此外,这些类文件并非立即全部都装入内存,而是根据程序需要装入内存。ClassLoader 是 JVM 中将类装入内存的那部分。 而且,Java ClassLoader 就是用 Java 语

风斗士 1002

城市NOA加速落地,BEV+Transformer引领自动驾驶感知新范式

数据闭环能力的建立,不仅依赖于数据规模,还依赖于数据的筛选、回传、标注、训练、验证与再部署,数据之于自动驾驶的价值再被印证的同时,也将推动自动驾驶迈向更为高阶的智能化时代。6月份,理想汽车向早鸟用户推送了首个不依赖高精地图的城市NOA。而特斯拉推出的基于BEV+Transformer的自动驾驶感知路线,可将2D图像转化为BEV鸟瞰图视角下的3D图像,并基于更庞大、更复杂、参数更多的感知算法模块,利用Transformer的注意力机制,将各个传感器统一到同一个连续的四维(三维空间+一维时间)时空中。

manfukeji的博客 1398

GEE:连续变化检测 CCD 第一步(导出ee.Algorithms.TemporalSegmentation.Ccdc函数的结果)

连续变化检测与分类(Continuous Change Detection and Classification, CCDC)主要有两个组件,一个连续变化检测 CCD,另外一个分类。在 Google Earth Engine (GEE)平台上进行 CCD 时间序列变化检测的时候,为了防止内存超限问题,将代码分为2阶段执行。第一阶段是运行 `ee.Algorithms.TemporalSegmentation.Ccdc` 函数,本文将详细介绍 CCD 的第一阶段的代码。

养乐多的博客 2495

深入了解Java ClassLoader、Bytecode 、ASM、cglib(II)

三、ASM我们知道Java是静态语言,而python、ruby是动态语言,Java程序一旦写好很难在运行时更改类的行为,而python、ruby可以。不过基于bytecode层面上我们可以做一些手脚,来使Java程序多一些灵活性和Magic,ASM就是这样一个应用广泛的开源库。 ASM is a Java bytecode manipulation framework...

weixin_34214500的博客 80

【深度解析TI InstaSPIN】无传感器FOC控制的核心方案

TI InstaSPIN通过“自动识别+通用观测器+开源工具链”的组合,解决了无传感器FOC控制开发难度大、周期长的核心痛点。其核心优势在于快速统一软件观测器的通用性与高精度,以及Fly Start闭环零速启动策略的高可靠性,可适配空调压缩机等家电电机的复杂运行需求。在空调外机双电机控制场景中,InstaSPIN与TI C2000系列MCU(F280013x/F28E12x)完美契合,借助MCU的高性能DSP内核与丰富外设,可实现双电机的精准同步控制,同时降低硬件成本与开发周期。

昔时扬尘处 326

第3章:OpenJDK从源码到字节码——Class 文件与 javac 管线

文章摘要 本文通过一个团队从JDK 8升级到JDK 21时遇到的反射异常问题,揭示了Java字节码层面的兼容性挑战。项目背景中指出了开发者面临的三大痛点:黑盒编译、语法糖陷阱和字节码增强盲区。随后通过师徒对话的形式,生动讲解了Class文件结构(魔数、常量池)和关键字节码指令(如invokevirtual等)。最后给出实战示例,分析自动装箱、泛型、lambda等语法糖在字节码层面的实现原理,帮助开发者建立字节码阅读能力,解决跨版本兼容性问题。

davidwang456的专栏 499

android 蓝牙通讯demo

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

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

JVM 常见面试问答:深入底层原理

本文为Java后端开发、架构师及中间件开发岗位面试提供全面的JVM知识体系,涵盖内存模型、对象创建、类加载、垃圾回收、JIT编译、性能调优等核心内容。内容分为14个章节,从基础概念到高级场景实战,包括: JVM内存模型:程序计数器、虚拟机栈、堆、方法区等运行时数据区详解。 对象创建与内存分配:对象实例化过程、TLAB机制、逃逸分析等。 类加载机制:双亲委派模型、类加载阶段、自定义类加载器。 垃圾回收:分代回收算法、CMS/G1/ZGC等回收器对比与原理。

weixin_72753562的博客 1017

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

深入了解Java ClassLoader、Bytecode 、ASM、cglib

一、Java ClassLoader 1,什么是ClassLoader 与 C 或 C++ 编写的程序不同,Java 程序并不是一个可执行文件,而是由许多独立的类文件组成,每一个文件对应于一个 Java 类。 此外,这些类文件并非立即全部都装入内存,而是根据程序需要装入内存。Cl

技术收藏 2719

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

fastjson classloader问题处理与原因分析

前言 最近做项目,一个业务使用了多重classloader隔离,在fastjson转换toJson时,直接报类转换异常了。分析了一段时间,记录分析原因 1. demo模拟 涉及类自定义加载,这里项目结构如下 自定义classloader,打破双亲委派并相互切换 package com.feng.fastjson.demo; import com.alibaba.fastjson.JSON; import com.feng.demo.common.Cat; import java.io.F

fenglllle的博客 2105

java FullGC问题解决示例

java FullGC问题解决示例 环境 JDK版本:jdk1.7.45 操作系统:linux 问题背景 某系统(后面称:系统A)接入监控平台之后,收到java虚拟机持久代FullGC报警通知。对此我们对这个问题进行了分析,分析过程如下: 查看JVM持久代统计信息: 执行命令:ps -ef|grep java, jmap -permstat 8698 JVM持久代类信息如下(部分数据): 持...

liguoxi666 1356

CGLIB入门系列二,CGLIB生成代理类的过程

AbstractClassGenerator 我们使用Enhancer来生成代理类,最终可以发现是调用了父类AbstractClassGenerator的方法,该类可以算是CGLIB中比较重要的一个类了,可以说所有cglib内部使用proxy的地方都需要继承这个类作为父类。AbstractClassGenerator内部维护了两级缓存,抽象了很多操作,并且定义了一些抽象方法用于具体的Generat...

P19777的博客 1165

ASM字节码操作库---入门环境搭建

ASM可以对字节码数据做修改,然后生成一份新的字节码文件,而且ASM还可以在什么都没有的情况下,直接生成一个.class文件。本文的demo就是演示这个场景,除此之外,ASM还能做分析操作,分析操作是指它可以对一份字节码做分析统计的操作,但是不生成新的字节码文件,也就是说它只是单纯分析,不做任何修改。本文使用JAVA语言作为ASM的演示demo。

知识应该共享,创造才应收费 1241

asm中的ClassWriter使用、自定义ClassVisitor和cglib的enhancer使用实例

文章目录ClassWriter的使用自定义一个ClassVisitorenhancer的使用 ASM是Java中比较流行的用来读写字节码的类库,用来基于字节码层面对代码进行分析和转换。在读写的过程中可以加入自定义的逻辑以增强或修改原来已编译好的字节码,比如CGLIB用它来实现动态代理。ASM被设计用于在运行时对Java类进行生成和转换,当然也包括离线处理。ASM短小精悍、且速度很快,从而避免在运行时动态生成字节码或转换时对程序速度的影响,又因为它体积小巧,可以在很多内存受限的环境中使用。 ClassWri

qq_41358574的博客 1968
上一篇: 关于protected访问权限的一个错误认识
下一篇: Base64编码和解码
Jim20
博客等级 码龄18年 34粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值