- 浏览: 848152 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
loveseed1989:
您好,我用您的方法运行Cone.java,会给我报java.l ...
vtk学习笔记 --- 编译vtk库和java库 -
60love5:
60love5 写道首先谢谢你的解析,但你这个验证可见性的小程 ...
多线程中共享对象的可见性 -
60love5:
首先谢谢你的解析,但你这个验证可见性的小程序是存在问题的,你的 ...
多线程中共享对象的可见性 -
Gamehu520:
...
java 中的Unsafe -
shanpao1234560:
这个list不是静态的第一种情况下也会有线程安全的问题么,求指 ...
一个看似线程安全的示例
2.2.5移除类成员
前面例子中用来修改类版本号的方法也可以用在ClassVisitor接口中的其它方法上。例如,通过修改visitField和visitMethod方法中的access核name,你可以修改一个字段或者方法的访问修饰符和名称。更进一步,除了转发修改该参数的方法调用,你也可以选择不转发该方法调用,这样做的效果就是,对应的类元素将被移除。
例如,下面的类适配器将移除外部类和内部类,同时移除源文件的名称(修改过的类仍然是功能完整的,因为这些元素仅用作调试)。这主要是通过保留visit方法为空来实现。
public class RemoveDebugAdapter extends ClassAdapter {
public RemoveDebugAdapter(ClassVisitor cv) {
super(cv);
}
@Override
public void visitSource(String source, String debug) {
}
@Override
public void visitOuterClass(String owner, String name, String desc) {
}
@Override
public void visitInnerClass(String name, String outerName,
String innerName, int access) {
}
}
上面的策略对字段和方法不起作用,因为visitField和visitMethod方法必须返回一个结果。为了移除一个字段或者一个方法,你不能转发方法调用,而是返回一个null。下面的例子,移除一个指定了方法名和修饰符的方法(单独的方法名是不足以确定一个方法,因为一个类可以包含多个相同方法名的但是参数个数不同的方法):
public class RemoveMethodAdapter extends ClassAdapter {
private String mName;
private String mDesc;
public RemoveMethodAdapter(
ClassVisitor cv, String mName, String mDesc) {
super(cv);
this.mName = mName;
this.mDesc = mDesc;
}
@Override
public MethodVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
if (name.equals(mName) && desc.equals(mDesc)) {
// do not delegate to next visitor -> this removes the method
return null;
}
return cv.visitMethod(access, name, desc, signature, exceptions);
}
}
2.2.6增加类成员
除了传递较少的方法调用,你也可以传递更多的方法调用,这样可以实现增加类元素。新的方法调用可以插入到原始方法调用之间,同时visitXxx方法调用的顺序必须保持一致(参看2.2.1)。
例如,如果你想给类增加一个字段,你需要在原始方法调用之间插入一个visitField调用,并且你需要将这个新的调用放置到类适配器的其中一个visit方法之中(这里的visit是指以visit打头的方法)。你不能在方法名为visit的方法中这样做,因为这样会导致后续对visitSource,visitOuterClass,visitAnnotation或者visitAttribute方法的调用,这样做是无效的。同样,你也不能将对visitField方法的调用放置到visitSource,visitOuterClass,visitAnnotation或者visitAttribute方法中。可能的位置是visitInnerClass,visitField,visitMethod和visitEnd方法。
如果你将这个调用放置到visitEnd中,字段总会被添加,除非你添加了显示的条件,因为这个方法总是会被调用。如果你把它放置到visitField或者visitMethod中,将会添加好几个字段,因为对原始类中每个字段或者方法的调用都会导致添加一个字段。两种方案都能实现,如何使用取决于你的需要。例如,你恶意增加一个单独的counter字段,用来统计对某个对象的调用次数,或者针对每个方法,添加一个字段,来分别统计对每个方法的调用。
注意:事实上,添加成员的唯一正确的方法是在visitEnd方法中增加额外的调用。同时,一个类不能包含重复的成员,而确保新添加的字段是唯一的方法就是比较它和已经存在的成员,这只能在所有成员都被访问之后来操作,例如在visitEnd方法中。程序员一般不大可能会使用自动生成的名字,如_counter$或者_4B7F_可以避免出现重复的成员,这样就不需要在visitEnd中添加它们。注意,如在第一章中讲的,tree API就不会存在这样的限制,使用tree API就可以在转换的任何时间点添加新成员。
为了展示上面的讨论,下面是一个类适配器,用来给一个类增加一个字段,除非这个字段已经存在:
public class AddFieldAdapter extends ClassAdapter {
private int fAcc;
private String fName;
private String fDesc;
private boolean isFieldPresent;
public AddFieldAdapter(ClassVisitor cv, int fAcc, String fName,
String fDesc) {
super(cv);
this.fAcc = fAcc;
this.fName = fName;
this.fDesc = fDesc;
}
@Override
public FieldVisitor visitField(int access, String name, String desc,
String signature, Object value) {
if (name.equals(fName)) {
isFieldPresent = true;
}
return cv.visitField(access, name, desc, signature, value);
}
@Override
public void visitEnd() {
if (!isFieldPresent) {
FieldVisitor fv = cv.visitField(fAcc, fName, fDesc, null, null);
if (fv != null) {
fv.visitEnd();
}
}
cv.visitEnd();
}
}
这个字段是在visitEnd方法中添加的。重写visitField方法不是为了修改已经存在的字段,而是为了检测我们希望添加的字段是否已经存在。注意,在调用fv.visitEnd之前,我们测试了fv是否为空,如我们前面所讲,一个class visitor的visitField方法可以返回null。
2.2.7转换链
到目前为止,我们看到了一些有ClassReader,一个类适配器和ClassWriter组成的转换链。当然,也可以将多个类适配器连接在一起,来实现更复杂的转换链。链接多个类适配器运行你组合多个独立的类转换,以实现更复杂的转换。注意,一个转换链条没必要是线性的,你可以编写一个ClassVisitor,然后同时转发所有的方法调用给多个ClassVisitor:
public class MultiClassAdapter implements ClassVisitor {
protected ClassVisitor[] cvs;
public MultiClassAdapter(ClassVisitor[] cvs) {
this.cvs = cvs;
}
@Override public void visit(int version, int access, String name,
String signature, String superName, String[] interfaces) {
for (ClassVisitor cv : cvs) {
cv.visit(version, access, name, signature, superName, interfaces);
}
}
...
}
相对地,多个类适配器也可以将方法调用都委托给相同的ClassVisitor(这需要额外的小心,以确保visit和visitEnd方法只被调用一次)。如图2.8这样的转换链也是可能地。
图2.8:一个复杂的转换链
发表评论
-
基于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 1689java虚拟机字节码执行引擎思维导图总结: 参考《深入理 ... -
java 垃圾回收相关总结 【思维导图】
2012-12-21 19:03 3289java垃圾回收相关总结: 参考《深入理解java ... -
java并发中的延迟初始化
2012-12-12 19:17 4708在《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 4209在看一些代码的时候,会发现在定义long型和double型的 ... -
多线程中共享对象的可见性
2012-12-08 18:52 5158在阅读《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 2160下载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软件介绍: 联通话费速查是一款针对联通 ...
相关推荐
### ASM3.0指南翻译——深入理解Java字节码引擎库 #### 1. 引言与背景 在软件开发领域,程序分析、生成及转换技术的应用极为广泛,覆盖从语法解析到语义分析,再到代码优化、混淆、调试、性能监控及面向切面编程等...
根据提供的文件信息,以下是关于“ASM4使用指南.pdf”文档中所提及知识点的详细介绍: 1. ASM库介绍: ASM(Java字节码操作和分析框架)是一个Java字节码操作与分析框架。它被设计用于直接以类文件的形式读写和修改...
根据给定的文件信息,我们可以提炼出以下几个关键的知识点,主要围绕着ASM30-LINK30和实用程序用户指南,以及Microchip Technology Inc.的相关信息进行深入解析: ### 1. 微芯科技(Microchip Technology Inc.)...
在压缩包中的"读我.txt"文件,很可能是C32Asm的使用指南或注意事项,它可能包含了安装步骤、配置选项、命令行参数以及一些使用技巧。而"c32asm"可能是个可执行文件,即C32Asm工具本身,或者是一个示例文件,用于演示...
《汇编程序员之代码风格指南》,此书是我自己翻译的中文版,网上已有很多 地方可下载,学习汇编语言而不注意编码风格是很吃亏的事,此书能教你什么时候 该做什么,什么时候不应该做什么。良好的编码风格对于win32...
描述中提到的“汉化了的,好用”,意味着这个win32asm工具已经被翻译成了中文,这对于中文用户来说是一个极大的便利,因为它消除了语言障碍,使得不懂英文的开发者也能轻松使用。通常,反汇编器的界面和文档都是英文...
src DCD 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4 dst DCD 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 END ``` 该程序定义了两个缓冲区`src`和`dst`,并通过循环将`src`中的...
本指南由著名的汇编语言专家Randall Hyde撰写,并由jhkdiy翻译成中文版。该指南旨在帮助程序员理解如何提高他们所编写的汇编代码的可读性。书中通过一系列实例来展示常见的问题及其解决方案,这些实例均来自互联网上...
本中文手册是由一位热心人士翻译整理的,其内容主要摘自GNU C编译器的官方文档。手册旨在为用户提供一个简明扼要的GCC使用指南,特别是针对编译器选项的解释。 #### 二、手册重要声明 1. **免责声明**:手册的内容...
译期:2006-6-11 邮箱:jhkdiy_gzb@21cn.net 潜水论坛:www.20cn.net 源教程版本:1.02 -2003年 译注:自己还是第一次翻译16页的英文教程。全部翻译完了,给我的感觉就是这篇文章是为已有汇编基础但从未...
- `ReadMe.txt`:通常包含项目说明、使用指南或者注意事项。 - `ConsoleApplication1`:可能是C++编译生成的可执行程序,包含了汇编和反汇编的功能。 - `汇编与反汇编exe`:这可能是最终生成的汇编和反汇编器的可...
- 中文伪指令.txt 可能包含了易语言中的特殊指令,这些指令在易语言中用中文表示,但被翻译为对应的汇编指令。 - 测试代码.txt 包含了一些示例代码,用于测试软件的功能和性能。 - 高级指令.txt 可能介绍了更复杂或...
### Linux 汇编语言开发指南 #### 一、简介 汇编语言作为一种低级语言,在现代编程领域中虽然不如高级语言那样普及广泛,但它在特定场景下的优势不容忽视。尤其是在Linux环境中,汇编语言被用于优化性能敏感的模块...
- `PRO/Emenu_translatyesnopro/enno-yes-both` 可能指的是菜单的翻译设置,用户可以根据需要选择中文、英文或者是双语界面。 - `menu_fontARIAL`:指定菜单使用的字体为Arial,确保了软件界面的一致性和可读性。 ...
2. **限制性使用**:根据许可证协议中的规定,用户不得擅自复制、翻译、广播、修改、授权、传输、分发、展示或表演软件的任何部分,除非许可证协议中有明确规定或许可,或者法律允许的情况。 3. **反向工程禁止**:...
在提供的文件列表中,"huibian.doc"可能是关于ASM乐曲程序设计的一个指南或教程,可能详细介绍了如何编写和调试ASM代码以创建音乐程序。而"www.pudn.com.txt"可能是从一个编程讨论论坛或资源网站下载的资料,可能...
2. **Win32汇编编程指南**: - **Win32环境下的开发工具**:介绍用于编写、编译和调试Win32汇编程序所需的工具链。 - **创建Win32汇编应用程序**:讲解如何从零开始构建一个简单的Win32汇编程序。 - **Win32 API...