1.ASM简介
ASM为Assembly的简写,意思是指装配。ASM指令的含义为汇编指令(泛指Intel
80X86 CPU中的指令集)。 ASM指令是为编程人员编写程序准备的,编译器将会把ASM指令真正的翻译成机器代码(能控制CPU做出操作的代码)。ASM可以操作的粒度在指令级别,具有性能好,灵活度高,功能强大的特点。关于ASM指令集合的具体介绍,参考下面的链接:http://blog.csdn.net/thisinnocence/article/details/50936470 ;大家可以根据自己的情况百度一下。
2.应用举例
ASM到底有什么作用呢?关于java的class文件进行热替换应该或多或少的知道一点,通俗的来讲就是在不关闭服务器的情况下,对class文件内容进行替换,达到增加功能的目的。不清楚的参考下面的链接:
https://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls/,具体介绍了热替换的原理和应用举例。热替换操作的对象是java的class文件,而不是指令级别的操作,而ASM是对java文件的指令级别的操作,这样的话速度更快!关于热替换的举例大家可以自己百度一下,在这里列举一个ASM的例子。
背景:统计函数执行时间,将开始和结束时间添加到相应的操作中。Account.java模拟耗时的函数:
package asmtimer;
public class Account {
public void operation(){
System.out.println("operations.....");
try{
Thread.sleep(10);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
TimeStat计时统计函数:
package asmtimer;
public class TimeStat {
static ThreadLocal t=new ThreadLocal<>();
public static void start(){
t.set(System.currentTimeMillis());
}
public static void end(){
long time=System.currentTimeMillis();
System.out.println(Thread.currentThread().getStackTrace()[2]+"speed:");
System.out.println(time);
}
}
下面是重点,将TimeStat中的函数对Account函数进行及时功能,TimeStatWeaveGenerator类主要是生成合并后的.class文件,里面具有函数统计功能,
package asmtimer;
import java.io.File;
import java.io.FileOutputStream;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
public class TimeStatWeaveGenerator {
public static void main(String[] args) throws Exception{
String className=Account.class.getName();
ClassReader cr=new ClassReader(className);
ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS);
TimeStatClassAdapter classAdapter=new TimeStatClassAdapter(cw);
cr.accept(classAdapter, ClassReader.SKIP_DEBUG);
byte[] bytes=cw.toByteArray();
FileOutputStream fOutputStream=new FileOutputStream(new File("bin/"+className.replaceAll("\.", "/")+".class"));
fOutputStream.write(bytes);
fOutputStream.close();
}
}
TimeStatClassAdapter类:
package asmtimer;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
public class TimeStatClassAdapter extends ClassAdapter {
public TimeStatClassAdapter(ClassVisitor cv){
super(cv);
}
public MethodVisitor visitMethod(final int access,final String name,
final String desc,final String signature,
final String[] exceptions){
MethodVisitor mv=cv.visitMethod(access, name, desc, signature, exceptions);
MethodVisitor wrappedMv=mv;
if(mv!=null){
if(name.equals("operation")){
wrappedMv=new TimeStatMethodAdapter(mv);
}
}
return wrappedMv;
}
}
TimeStatMethodAdaptor类:package asmtimer;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class TimeStatMethodAdapter extends MethodAdapter{
public TimeStatMethodAdapter(MethodVisitor ss){
super(ss);
}
@Override
public void visitCode(){
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "asmtimer/TimeStat",
"start", "()V");
super.visitCode();
}
@Override
public void visitInsn(int opcode){
if(opcode>=Opcodes.IRETURN&&opcode<=Opcodes.RETURN){
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "asmtimer/TimeStat",
"end", "()V");
}
mv.visitInsn(opcode);
}
}
测试类:package asmtimer;
public class RunAccountMain {
public static void main(String[] args){
Account account=new Account();
account.operation();
}
}
在没有运行TimeStatWeaveGenerator类,直接运行RunAccountMain类,出现如下信息:
点击TimeStatWeaveGenerator类将bin对应文件下面的class文件替换掉,再一次运行RunAccountMain类,出现如下信息:可以通过javap命令查看字节码:由于生成的文件比较长,只粘贴一部分,大家可以自己运行一下。原来的Account类字节码:增加时间统计功能后的Account:
3.相关资源
里面涉及的东西比较多,下面给大家提供一些关于ASM和一些类的资源链接:
1)Asm多继承举例:http://www.cnblogs.com/liuling/archive/2013/05/31/asmMutilExtends.html
2)Asm用户手册:http://download.forge.objectweb.org/asm/asm4-guide.pdf
3)Asm3.2 Api: http://asm.ow2.org/asm32/javadoc/user/index.html
4) Asm 源码地址:https://github.com/marchof/asm
5) Asm3.0中文API:https://wenku.baidu.com/view/bf486c4577232f60ddcca133.html
这些知识个人的学习总结,主要参考《实战虚拟机-jvm故障诊断与性能优化》,若有错误或者改进之处,请多多指导,谢谢!!!