- 浏览: 848238 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
loveseed1989:
您好,我用您的方法运行Cone.java,会给我报java.l ...
vtk学习笔记 --- 编译vtk库和java库 -
60love5:
60love5 写道首先谢谢你的解析,但你这个验证可见性的小程 ...
多线程中共享对象的可见性 -
60love5:
首先谢谢你的解析,但你这个验证可见性的小程序是存在问题的,你的 ...
多线程中共享对象的可见性 -
Gamehu520:
...
java 中的Unsafe -
shanpao1234560:
这个list不是静态的第一种情况下也会有线程安全的问题么,求指 ...
一个看似线程安全的示例
3.2接口和组件
3.2.1表现
ASM API中关于方法的生成和转换的部分是基于MethodVisitor接口的(见图3.4),该接口由ClassVisitor的visitMethod方法返回。除了一些与注解和调试相关的方法之外,这些将在后面章节中介绍,MethodVisitor接口还针对每个字节码指令分类定义了一个方法,这个分类是基于这些指令的编号以及参数的类型(这些分类与3.1.2章节中出现的分类并不对应)。这些方法必须按照下面给定的顺序来调用(还包含一些定义在MethodVisitor接口的JavaDoc文档中的限制):
visitAnnotationDefault?
( visitAnnotation | visitParameterAnnotation | visitAttribute )*
( visitCode
( visitTryCatchBlock | visitLabel | visitFrame | visitXxxInsn |
visitLocalVariable | visitLineNumber )*
visitMaxs )?
visitEnd
这就意味着,如果存在注解和属性,那么它们必须首先被调用,然后才是方法的字节码,这只针对非抽象方法。位于visitCode和visitMax方法之间的这些方法,必须按照顺序来调用,并且visitCode和visitMax只能调用一次。
public interface MethodVisitor {
AnnotationVisitor visitAnnotationDefault();
AnnotationVisitor visitAnnotation(String desc, boolean visible);
AnnotationVisitor visitParameterAnnotation(int parameter,
String desc, boolean visible);
void visitAttribute(Attribute attr);
void visitCode();
void visitFrame(int type, int nLocal, Object[] local, int nStack,
Object[] stack);
void visitInsn(int opcode);
void visitIntInsn(int opcode, int operand);
void visitVarInsn(int opcode, int var);
void visitTypeInsn(int opcode, String desc);
void visitFieldInsn(int opc, String owner, String name, String desc);
void visitMethodInsn(int opc, String owner, String name, String desc);
void visitJumpInsn(int opcode, Label label);
void visitLabel(Label label);
void visitLdcInsn(Object cst);
void visitIincInsn(int var, int increment);
void visitTableSwitchInsn(int min, int max, Label dflt,
Label labels[]);
void visitLookupSwitchInsn(Label dflt, int keys[], Label labels[]);
void visitMultiANewArrayInsn(String desc, int dims);
void visitTryCatchBlock(Label start, Label end, Label handler,
String type);
void visitLocalVariable(String name, String desc, String signature,
Label start, Label end, int index);
void visitLineNumber(int line, Label start);
void visitMaxs(int maxStack, int maxLocals);
void visitEnd();
}
图3.4 MethodVisitor接口
在一系列的事件中,visitCode和visitMaxs可以被用来检测方法字节码的开始和结束。就像类一样,visitEnd方法必须最后被调用,同时可以用来检测类的结束。
ClassVisitor和MethodVisitor可以一定的顺序合并起来以生成更复杂的类:
ClassVisitor cv = ...;
cv.visit(...);
MethodVisitor mv1 = cv.visitMethod(..., "m1", ...);
mv1.visitCode();
mv1.visitInsn(...);
...
mv1.visitMaxs(...);
mv1.visitEnd();
MethodVisitor mv2 = cv.visitMethod(..., "m2", ...);
mv2.visitCode();
mv2.visitInsn(...);
...
mv2.visitMaxs(...);
mv2.visitEnd();
cv.visitEnd();
注意,这里没有必要结束一个方法的访问之后再去访问另外一个,事实上,MethodVisitor接口是完全独立的,它们可以任何顺序来使用,只要cv.visitEnd()方法还未被调用:
ClassVisitor cv = ...;
cv.visit(...);
MethodVisitor mv1 = cv.visitMethod(..., "m1", ...);
mv1.visitCode();
mv1.visitInsn(...);
...
MethodVisitor mv2 = cv.visitMethod(..., "m2", ...);
mv2.visitCode();
mv2.visitInsn(...);
...
mv1.visitMaxs(...);
mv1.visitEnd();
...
mv2.visitMaxs(...);
mv2.visitEnd();
cv.visitEnd();
ASM提供了三个基于MethodVisitor接口的组件来生成和转换方法:
- ClassReader解析编译后方法的内容,然后调用MethodVisitor接口中对应的方法,其中MethodVisitor实例由ClassVisitor返回,而ClassVisitor实例被当做参数传递给ClassReader的accept方法。
- ClassWriter的visitMethod方法返回MethodVisitor接口的一个实现,由它来直接以二进制的方式构建编译后的方法。
- MethodAdapter是MethodVisitor的一个实现,它将自己接受的方法调用委托给其他的MethodVisitor实例。
ClassWriter的选项
如我们在3.1.5章节中所见,计算一个方法的栈映射帧并不容易:你必须计算所有的帧,找到与跳转目标以及那些无条件跳转想对应的帧,最后压缩这些帧。同样地,计算一个方法的局部变量和操作数栈的大小也不容易,虽然相对而言容易点。
令人高兴地是,ASM可以为你计算这些东西。当你创建一个ClassWriter时,你可以指定哪些是需要自动计算的:
- new ClassWriter(0) 将不会自动进行计算。你必须自己计算帧、局部变量和操作数栈的大小。
- new ClassWriter(ClassWriter.COMPUTE_MAXS) 局部变量和操作数栈的大小就会自动计算。但是,你仍然需要自己调用visitMaxs方法,尽管你可以使用任何参数:实际上这些参数会被忽略,然后重新计算。使用这个选项,你仍然需要计算帧的大小。
- new ClassWriter(ClassWriter.COMPUTE_FRAMES) 所有的大小都将自动为你计算。你也不许要调用visitFrame方法,但是你仍然需要调用visitMaxs方法(参数将被忽略然后重新计算)。
使用这些选项是方便很多,但是会带来一些损失:COMPUTE_MAXS选项将使得ClassWriter慢10%,使用COMPUTE_FRAMES选项将使得ClassWriter慢两倍。你必须将它与自己计算花费的时间相比较:与ASM提供的算法相比较,在某些特定的情况下,这里有一些更容易和快速的算法来进行计算,但是必须处理所有的情形。
如果你选择自己计算这些帧的大小,你可以让ClassWriter来帮你进行帧压缩。这样的话,你只能使用visitFrame(F_NEW,nLocals,locals,nStack,stack)方法去访问那些未被压缩的帧,nLocals和nStack代表局部变量和操作数栈的大小,locals和stack是一些包含对应类型的数组(参看JavaDoc)。
注意,为了自动计算帧的大小,有时必须计算两个类共同的父类。缺省情况下,ClassWriter将会在getCommonSuperClass方法中计算这些,通过在加载这两个类进入虚拟机时,使用反射API来计算。但是,如果你将要生成的几个类相互之间引用,这将会带来问题,因为引用的类可能还不存在。在这种情况下,你可以重写getCommonSuperClass方法来解决这个问题。
3.2.2生成方法
在3.1.3节中定义的getF方法字节码可以通过下面的方法调用来生成,其中mv为MethodVisitor:
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "pkg/Bean", "f", "I");
mv.visitInsn(IRETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
从第一个方法开始进行字节码生成,紧跟着的三个方法调用用来生成方法中的代码(字节码和ASM API之间的映射还是很简单的)。visitMaxs方法必须在其他方法被调用之后再调用,它是用来这个方法的执行帧中局部变量和操作数栈的大小的。如在3.1.3节中见到的,一个方框表示一部分。最后的方法调用是用来结束方法的生成。
相应地,setF方法和构造方法也可以相似的方式来生成。一个比较有意思的例子是checkAndSetF方法:
mv.visitCode();
mv.visitVarInsn(ILOAD, 1);
Label label = new Label();
mv.visitJumpInsn(IFLT, label);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ILOAD, 1);
mv.visitFieldInsn(PUTFIELD, "pkg/Bean", "f", "I");
Label end = new Label();
mv.visitJumpInsn(GOTO, end);
mv.visitLabel(label);
mv.visitFrame(F_SAME, 0, null, 0, null);
mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL,
"java/lang/IllegalArgumentException", "<init>", "()V");
mv.visitInsn(ATHROW);
mv.visitLabel(end);
mv.visitFrame(F_SAME, 0, null, 0, null);
mv.visitInsn(RETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
在visitCode和visitEnd调用之间的方法调用和3.1.5节最后展示的字节码是精确映射的。每个调用对应一个指令,标签或者帧(唯一的例外就是label和end label的声明和构造)。
注意 一个label对象指定的指令就是那些紧跟在这个label的visitLabel方法调用之后。例如,end指定了RETURN指令,不是其后的frame,因为它不是一个指令。可以使用几个标签来指定相同的指令,但是一个标签必须指定一个指令。换句话说,可以针对不同的label连续调用visitLabel,但是在一个指令中使用的标签必须只能被visitLabel访问一次。最后一个限制就是标签不能共享,每个方法都有自己的标签。
发表评论
-
基于Oracle Streams + Oracle AQ 捕获变更,发布变更(二)
2014-11-21 22:23 3216要求:使用Oracle Streams捕获某个用户下部 ... -
基于Oracle Streams + Oracle AQ 捕获变更,发布变更(一)
2014-11-20 22:23 2806要求:使用Oracle Streams捕获某个用户下部分表 ... -
如何去掉在浏览器中打开java applet时的警告对话框
2013-08-24 12:10 6999好久没更新博客了! 最近,由于项目要求,需要将sw ... -
Android 内存泄露笔记
2013-03-05 23:10 01、大部分内存泄露都是错误的持有了Activity或者Con ... -
java 虚拟机总结 【思维导图】
2012-12-22 20:11 2098java虚拟机总结思维导图: 参考《深入理解jav ... -
Java虚拟机字节码执行引擎 【思维导图】
2012-12-22 19:51 1691java虚拟机字节码执行引擎思维导图总结: 参考《深入理 ... -
java 垃圾回收相关总结 【思维导图】
2012-12-21 19:03 3289java垃圾回收相关总结: 参考《深入理解java ... -
java并发中的延迟初始化
2012-12-12 19:17 4709在《java并发编程实战 ... -
java同步容器与并发容器
2012-12-09 18:07 4365何为同步容器:可以简 ... -
一个看似线程安全的示例
2012-12-09 14:56 5083在《java并发编程实战》第四章4.4.1节给出了一个程序示 ... -
多线程中的long和double
2012-12-08 19:26 4210在看一些代码的时候,会发现在定义long型和double型的 ... -
多线程中共享对象的可见性
2012-12-08 18:52 5161在阅读《java并发编程实战》的第三章的时候,看到书中的一个 ... -
一个快速、轻量级 Collection 库 Trove
2012-12-07 09:35 3769Trove一个快速、轻量级针对java原子类型(byte,i ... -
java 中的Unsafe
2012-12-05 22:25 32764在阅读AtomicInteger的源码时,看到了这个类:su ... -
在ubuntu10上编译Thrift0.8.0
2012-08-01 15:34 2161下载thrift0.8.0 ,地址: http:// ... -
生活小工具--记账小助手1.0发布
2012-05-31 15:08 1762因为自己平时喜欢记账,把每日的消费情况都记录下来,所以希望找 ... -
话费速查升级版v1.3发布
2012-05-04 12:47 1443前段时间开发了一个话费速查的小应用,最近一直保持每周更新一个 ... -
编译zeromq的java绑定:jzmq
2012-05-03 22:47 135521、 下载zeromq源码:http://www.ze ... -
Android软件包静默安装小应用 - 附源码
2012-04-21 20:50 12424老早之前,写了一个android软件包静默安装的应用,放在工 ... -
最方便的联通话费,余额查询软件来了! --- 联通话费速查v1.2
2012-04-12 18:01 4049软件介绍: 联通话费速查是一款针对联通 ...
相关推荐
这份中文指南将帮助开发者快速入门,通过实例和详细的解释,深入理解ASM的使用方法和最佳实践。 在阅读“ASM4使用指南.pdf”时,重点关注以下部分: - ASM的基本架构和核心组件介绍 - 如何使用ClassWriter和...
### ASM3.0指南翻译——深入理解Java字节码引擎库 #### 1. 引言与背景 在软件开发领域,程序分析、生成及转换技术的应用极为广泛,覆盖从语法解析到语义分析,再到代码优化、混淆、调试、性能监控及面向切面编程等...
根据提供的文件信息,以下是关于“ASM4使用指南.pdf”文档中所提及知识点的详细介绍: 1. ASM库介绍: ASM(Java字节码操作和分析框架)是一个Java字节码操作与分析框架。它被设计用于直接以类文件的形式读写和修改...
Java的asm文档,来自官方。asm4-guide.pdf。ASM 是一个 Java 字节码操控框架。...ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。说白了asm是直接通过字节码来修改class文件。
- Adding and removing class members:说明了如何使用ASM库向类中添加或移除成员(字段、方法等)。 - Generating classes:描述了如何使用ASM生成新的类。 - Parsing classes:说明了ASM如何解析已有的类文件。 ...
4. **类和方法的生成**:ASM提供了`ClassWriter`和`MethodWriter`类,它们可以用来生成新的类或方法的字节码,这对于动态代码生成非常关键。 5. **事件驱动的API设计**:ASM的设计基于事件驱动,这意味着在解析类或...
### asm操作指南(中文)知识点总结 #### 一、ASM框架简介 - **定义与功能**:ASM是一个Java字节码操纵框架,主要用于动态生成类或增强现有类的功能。通过直接生成二进制`.class`文件,ASM能够在类被加载到Java...
它不仅提供了关于如何使用库的详细指南,还对 ASM4 在程序分析、生成和转换方面的作用提供了深刻的理解。这不仅包括 ASM4 的基本概念和架构,还包括更高级的主题,例如如何利用 ASM4 实现高效的类文件分析和转换,...
在阅读《ASM指南》的过程中,你将逐步掌握ASM的基本用法,包括类、字段和方法的解析,以及如何生成和修改字节码。同时,书中还会提供丰富的示例代码,帮助你快速上手并应用于实际项目中。 总之,《ASM指南》是一本...
### ASM7使用指南知识点 #### 1. 引言与动机 **ASM**(Abstract Syntax Model)是一款专门针对Java字节码操作的强大工具库,它主要用于程序分析、生成及转换等场景。根据提供的文档信息来看,尽管标题为“ASM7使用...
2. **字节码生成**:除了解析,ASM还支持生成新的字节码,允许开发者动态创建或修改类和方法。这对于实现Java代理、AOP(面向切面编程)或者动态语言的JVM实现是非常关键的。 3. **高性能**:ASM设计时注重性能,其...
标题《asm4使用指南(强烈推荐)》以及描述《java使用asm4操作字节码技术,详细介绍了asm如何对java的字节码进行操作,强烈推荐》指明了文档的核心内容是介绍ASM4这一工具在Java字节码层面操作的指南,并且给出了...
#### 二、安装指南 **1.3 安装** - **1.3.1 在MS-DOS或Windows下的安装:** - 确保计算机上已安装了支持环境。 - 下载NASM的最新版本,解压缩后将其添加到系统路径中。 - **1.3.2 在Unix下的安装:** - 使用包...
ASM4使用指南. asm是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。asm可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。
ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以...ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。
在实际应用中,结合最佳实践和技术指南,可以使ASM更好地服务于企业级数据库环境。 #### 附录 - **查看和发现字符串**:提供了一系列视图和发现字符串,用于查询ASM的相关信息。 - **单个非ASM数据文件迁移到ASM**...
1. **文档**:这部分可能包括Javadoc文档,详细解释了ASM库中的各种类和方法,帮助开发者理解如何使用API。文档还可能包含用户指南、教程和示例代码,帮助初学者快速上手。 2. **jar文件**:ASM的核心库,即asm-*....