- 浏览: 848254 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
loveseed1989:
您好,我用您的方法运行Cone.java,会给我报java.l ...
vtk学习笔记 --- 编译vtk库和java库 -
60love5:
60love5 写道首先谢谢你的解析,但你这个验证可见性的小程 ...
多线程中共享对象的可见性 -
60love5:
首先谢谢你的解析,但你这个验证可见性的小程序是存在问题的,你的 ...
多线程中共享对象的可见性 -
Gamehu520:
...
java 中的Unsafe -
shanpao1234560:
这个list不是静态的第一种情况下也会有线程安全的问题么,求指 ...
一个看似线程安全的示例
3.2.4无状态转换
假定,我们想要测量一个程序中花费在每个类上的时间,那么我们需要在每个类上添加一个静态的计时字段,并且我们需要将每个方法的执行之间加到这个字段上。也就是说我们想转换类似于C这样的一个类:
public class C {
public void m() throws Exception {
Thread.sleep(100);
}
}
转换之后:
public class C {
public static long timer;
public void m() throws Exception {
timer -= System.currentTimeMillis();
Thread.sleep(100);
timer += System.currentTimeMillis();
}
}
为了弄清楚ASM是如何实现的,我们将编译这两个类,然后对比它们的TraceClassVisitor或者ASMifierClassVisitor的输出。通过TraceClassVisitor我们可以发现以下不同(粗体表示):
GETSTATIC C.timer : J
INVOKESTATIC java/lang/System.currentTimeMillis()J
LSUB
PUTSTATIC C.timer : J
LDC 100
INVOKESTATIC java/lang/Thread.sleep(J)V
GETSTATIC C.timer : J
INVOKESTATIC java/lang/System.currentTimeMillis()J
LADD
PUTSTATIC C.timer : J
RETURN
MAXSTACK = 4
MAXLOCALS = 1
通过上面我们看到了,我们必须在这个方法的最开始添加四条指令,以及在这个方法返回之前添加另外四条指令。最后 我们需要更新操作数栈的大小。因此,我们可以在方法适配器中重写这个方法以增加最开始的四条指令:
public void visitCode() {
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, owner, "timer", "J");
mv.visitMethodInsn(INVOKESTATIC, "java/lang/System",
"currentTimeMillis", "()J");
mv.visitInsn(LSUB);
mv.visitFieldInsn(PUTSTATIC, owner, "timer", "J");
}
在这里owner必须设置为即将转换的类的名字。现在我们需要添加另外四条位于RETURN之前的指令,同时这四条指令也必须位于xRETURN或者ATHROW之前,因为这些指令都会结束方法的执行。这些指令没有任何参数,并且都是通过visitInsn方法来访问。因此,我们可以重写这个方法来添加这四条指令:
public void visitInsn(int opcode) {
if ((opcode >= IRETURN && opcode <= RETURN) || opcode == ATHROW) {
mv.visitFieldInsn(GETSTATIC, owner, "timer", "J");
mv.visitMethodInsn(INVOKESTATIC, "java/lang/System",
"currentTimeMillis", "()J");
mv.visitInsn(LADD);
mv.visitFieldInsn(PUTSTATIC, owner, "timer", "J");
}
mv.visitInsn(opcode);
}
最后,我们仍然需要更新操作数栈的大小。这些指令中,我们往操作数栈中放置了两个long行数据,因此需要四个方框。在这个方法开始的时候,这个操作数栈是被初始化为空的,因此我们知道最开始的四条指令需要的栈大小为4.我们也知道,我们插入的代码对这个栈大小没有改变(因为从栈中弹出的数据与入栈的数据一样多)。结果是,如果最初的代码需要的栈大小为s,那么转换方法之后栈的大小的最大值为max(4,s)。不幸地是,我们还需要在RETURN指令之前添加四条指令,在这里我们不知道这个操作数栈的大小。我们只知道它的大小应该小于等于s。最后,我们可以认为在RETURN指令之前添加的代码需要的操作数栈的大小最大为s+4。这种最坏的情形在实际中很少发生:就一般的编译器而言,RETURN指令之前,操作数栈中一般只包含方法的返回值,那么它的大小就可能是0,1或者最大为2.但是,如果我们希望处理所有可能的情况,那么我们应该使用最坏的这种情况。所以,我们需要重写visitMaxs方法:
public void visitMaxs(int maxStack, int maxLocals) {
mv.visitMaxs(maxStack + 4, maxLocals);
}
当然了,我们也不必为操作数栈的大小而烦恼,我们可以依赖于COMPUTE_MAXS选项,它会为我们计算最优的值而不是最坏的值。同时,就这么一个简单的转换,也没必须花费这么经理来手动更新maxStack。
现在,一个有趣的问题是:如何处理栈映射帧?原始的代码不包含任何帧,转换后的代码页不包含,难道这是因为我们使用的例子很特殊吗?这里是否有一些情形帧必须被更新吗?答案是否定的,因为,第一,插入的代码没有改变操作数栈,第二,插入的代码没有包含跳转指令,第三,这些跳转指令,或者更正式的,程序的控制流没有修改。这意味着原始的帧没有改变,既然新插入的代码没有增加帧,那么原始帧压缩后也没有改变。
现在,我们可以将这些元素和ClassAdapter以及MethodAdapter结合起来:
public class AddTimerAdapter extends ClassAdapter {
private String owner;
private boolean isInterface;
public AddTimerAdapter(ClassVisitor cv) {
super(cv);
}
@Override public void visit(int version, int access, String name,
String signature, String superName, String[] interfaces) {
cv.visit(version, access, name, signature, superName, interfaces);
owner = name;
isInterface = (access & ACC_INTERFACE) != 0;
}
@Override public MethodVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
exceptions);
if (!isInterface && mv != null && !name.equals("<init>")) {
mv = new AddTimerMethodAdapter(mv);
}
return mv;
}
@Override public void visitEnd() {
if (!isInterface) {
FieldVisitor fv = cv.visitField(ACC_PUBLIC + ACC_STATIC, "timer",
"J", null, null);
if (fv != null) {
fv.visitEnd();
}
}
cv.visitEnd();
}
class AddTimerMethodAdapter extends MethodAdapter {
public AddTimerMethodAdapter(MethodVisitor mv) {
super(mv);
}
@Override public void visitCode() {
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, owner, "timer", "J");
mv.visitMethodInsn(INVOKESTATIC, "java/lang/System",
"currentTimeMillis", "()J");
mv.visitInsn(LSUB);
mv.visitFieldInsn(PUTSTATIC, owner, "timer", "J");
}
@Override public void visitInsn(int opcode) {
if ((opcode >= IRETURN && opcode <= RETURN) || opcode == ATHROW) {
mv.visitFieldInsn(GETSTATIC, owner, "timer", "J");
mv.visitMethodInsn(INVOKESTATIC, "java/lang/System",
"currentTimeMillis", "()J");
mv.visitInsn(LADD);
mv.visitFieldInsn(PUTSTATIC, owner, "timer", "J");
}
mv.visitInsn(opcode);
}
@Override public void visitMaxs(int maxStack, int maxLocals) {
mv.visitMaxs(maxStack + 4, maxLocals);
}
}
}
这里的类适配器是用来实例化方法适配器(除了构造方法),同时也用来添加计时字段和保存将被转换的类名到一个字段中,这样在方法适配器中可以访问到这个类名。
发表评论
-
基于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软件介绍: 联通话费速查是一款针对联通 ...
相关推荐
- `C32ASM.chm`:这通常是一个CHM(Compiled Help Manual)文件,即编译后的帮助文档,包含C32Asm的使用指南和参考信息。 - `C32asm.dll`:动态链接库文件,可能包含了C32Asm运行时需要的一些函数或服务。 - `C32...
ASM1153E是一款广泛应用在电子设备中的串行ATA(SATA)桥接芯片,它主要用于将SATA接口转换为其他类型的接口,如PCI-E,USB等,以便于数据传输和存储。固件刷写是更新该芯片内嵌软件的过程,以改善性能、修复错误或...
总结来说,这个主题涵盖了硬件组件(ASM1153E芯片)、外设优化(关闭休眠)、以及用户操作指南,是关于提升硬盘盒性能和效率的一个实践性教程。如果你需要关闭硬盘盒的休眠功能,这个工具和教程将非常有用。在操作前...
1. C32ASM.chm:这是帮助文档,通常包含软件的使用指南、功能介绍和常见问题解答。用户可以通过这个文件快速学习如何使用C32Asm.exe。 2. C32asm.dll:这是一个动态链接库文件,包含了C32Asm.exe运行所需的部分功能...
这些文档可能包括技术手册、代码示例、电路图和调试指南,帮助用户更好地理解和应用ASM步进电机。 总之,步进电机调速是通过改变脉冲频率、采用细分驱动和精确的正反转控制来实现的。ASM电机作为一个特定的电机类型...
2. **调试功能**:C32Asm编辑器内置了调试工具,允许用户设置断点、单步执行、查看寄存器状态和内存内容,这对于理解程序运行过程和查找错误至关重要。 3. **反汇编和二进制查看**:编辑器可能包含反汇编器功能,...
### 训练ASM英文文档知识点概述 #### 一、引言 - **Stasm**:一个C++软件包,主要用于定位面部图像中的特征点(即面部标志)。用户提供一张人脸图像,该软件能够返回这些特征点的位置。 - **适用场景**:Stasm主要...
ASM汇编语言全集是一份宝贵的资源,涵盖了汇编语言的各个方面,对于学习和深入理解计算机底层原理极其有用。汇编语言是计算机编程的一种低级语言,它与机器语言紧密相关,每一行汇编指令几乎都能直接转换为特定的...
### 将SAP数据库迁移至Oracle 11g R2 ASM的最佳实践指南 #### 概述 本指南旨在提供一个全面的技术文档,介绍如何将现有的SAP数据库迁移至Oracle 11g R2 ASM(自动存储管理)环境,并强调最佳实践以确保数据完整性和...
描述中提到的“汉化了的,好用”,意味着这个win32asm工具已经被翻译成了中文,这对于中文用户来说是一个极大的便利,因为它消除了语言障碍,使得不懂英文的开发者也能轻松使用。通常,反汇编器的界面和文档都是英文...
《MCS51_ASM_IDE_2812:全面解析单片机开发的强大工具》 在电子工程和嵌入式系统的世界里,MCS51系列单片机以其高效能和广泛应用而闻名。为了更好地支持这些单片机的开发工作,出现了"MCS51_ASM_IDE_2812"这样的...
- 2004-12-14: M. Müller, P. Walden 和 G. Blechschmidt 发布版本 - 2005-02-02: G. Blechschmidt 进行了小幅度修正 - 2005-04-08: G. Blechschmidt 适应新版本 GAA30785AAC,并增加了 ASM 机器类型 (MCS220 ...
2. 在PC机和实验系统联机状态下,新建实验程序,编辑完成后进行保存(保存后缀为.asm 文件)。 3. 编译下载。 4. 全速运行,运行程序。 5. 按 RST 键退出。 七、实验程序 实验程序主要包括两个部分:数据段和代码...
- **视图V$ASM_DISK**:列出ASM实例中的所有磁盘及其状态。 - **常用方法** - **如何确定ASM实例的编号**:解释如何查找ASM实例的标识符。 - **查询DG-RAW-磁盘的对应关系**:查询diskgroup与磁盘之间的关联。 ...
### ARM编译器参考指南知识点总结 #### 一、ARM RealView 编译工具 (RVCT) 概述 **1.1 关于ARM编译器** - **RealView 编译工具 (RVCT)**:这是一套由ARM公司开发的专业编译工具,主要用于ARM架构下的软件开发。 -...
标题中的“ds18.rar_DS18B20 ASM_ds18”暗示了这个压缩包主要涉及DS18B20数字温度传感器的程序代码,其中可能包含了使用汇编语言(ASM)编写的代码。DS18B20是一款单线数字温度传感器,由达拉斯半导体(现为Maxim ...
【MCS51_ASM_IDE】是一款专为51系列微控制器设计的汇编语言集成开发环境(IDE),它提供了全面的功能,使开发者能够高效地编写、编译和调试51汇编代码。51汇编器是这个IDE的核心部分,它支持8051、8052等51家族的微...
《Intel® 64 and IA-32 Architectures Software Developer’s Manual》是Intel公司为开发者提供的权威指南,详细阐述了Intel 64(也称为x86-64)和IA-32架构的硬件特性、指令集以及编程模型。这份手册对于深入理解...