JAVA字节码文件操作技巧(3)

    技术2022-07-03  138

    http://developer.51cto.com  2010-09-25 10:20  admin  qa.taobao.com  我要评论(0) 本文将介绍与操作Java字节码有关的基本知识和操作Java字节码的方法及Demo,谈到操作Java字节码,不能不谈到AOP,这里向大家做一下简单介绍。   IBM发布Java字节码配置工具包BIPTK 深入学习JVM内存设置原理和调优 JVM.dll装载过程与源代码分析 巧解使Eclipse崩溃的JVM terminated问题 解决JVM Terminated.ExitCode=-1问题行之有效的方法

     

    下面我们来操作一下Java字节码文件HelloTaobao.class:

    1.想操作Java字节码的某一方法,需要继承ASM中的ClassAdapter和MethodAdapter

    2.定义类Generator来读入Java字节码文件HellTaobao,改造Java字节码文件,生成改造后的同名Java字节码文件HellTaobao,代码如下:

    publicclassGenerator  {  publicstaticvoidmain(String[]args)throwsException  {  ClassReadercr=newClassReader(“HellTaobao”);   ClassWritercw=newClassWriter(ClassWriter.COMPUTE_MAXS);   ClassAdapterclassAdapter=newByteCodeClassHandler(cw);   cr.accept(classAdapter,ClassReader.SKIP_DEBUG);   byte[]data=cw.toByteArray();   Filefile=newFile(“HellTaobao.class”);   FileOutputStreamfout=newFileOutputStream(file);   fout.write(data);   fout.close();  }  }   

    3.ByteCodeClassHandler(自定义)类继承ClassAdapter(fromASM)

    4.ByteCodeClassHandler类中重写visitMethod,这个方法里去判断如果Java字节码文件HelloTaobao.class包含方法helloHeyun就调用ByteCodeMethodHandler类

    publicclassByteCodeClassHandlerextendsClassAdapter  {  publicByteCodeClassHandler(ClassVisitorcv)  {  super(cv);  }  publicvoidvisit(intversion,intaccess,Stringname,Stringsignature,  StringsuperName,String[]interfaces)  {  super.visit(version,access,name,signature,superName,interfaces);  }  publicvoidvisitSource(Stringsource,Stringdebug)  {  super.visitSource(source,debug);   }  publicvoidvisitEnd()  {  }   @Override   publicMethodVisitorvisitMethod(intaccess,Stringname,Stringdesc,   Stringsignature,String[]exceptions)  {  MethodVisitormv=cv.visitMethod(access,name,desc,signature,   exceptions);   MethodVisitorwrappedMv=mv;   if(mv!=null)   {   //对于”helloHeyun”方法进行改造   if(name.equals(“helloHeyun”))  {   //使用自定义MethodVisitor,改写方法内容   wrappedMv=newByteCodeMethodHandler(mv);  }  }  returnwrappedMv;  }  }   

    5.ByteCodeMethodHandler(自定义)继承MethodAdapter(fromASM),这里来做改造想要调用的自定义方法,这里将调用类ControlByteCode(自定义)中的controlByteCodeByHeyun(自定义)方法

    publicclassByteCodeMethodHandlerextendsMethodAdapter  {  publicByteCodeMethodHandler(MethodVisitormv)  {  super(mv);  }  publicvoidvisitCode()  {  visitMethodInsn(Opcodes.INVOKESTATIC,“ControlByteCode”,   “controlByteCodeByHeyun”,“()V”);  }  }   

    6.ControlByteCode类的controlByteCodeByHeyun方法如下

    publicclassControlByteCode  {  publicstaticvoidcontrolByteCodeByHeyun()  {  System.out.println(“Thismethodhasalreadybeencovered.”);   //TODOrealsecuritycheck  }  }  

    7.这样,当运行完Generator类中main方法后,会生成一个和原Java字节码文件同名的文件(可以观察出,会比以前的文件大,当然也可以用MD5来确定是两个不同文件)。

    8.此时在运行主方法类Main,会发现在Console打印如下:

    Hello,ThisisHeyun’sinvestigationaboutcodecoverage!   Thismethodhasalreadybeencovered.  

    9.由此,可以看出,在原功能没有变化的前提下,通过改变Java字节码文件,我们实现了CodeCoverage的雏形。实际上,很多CodeCoverage工具(如Cobertura)都是运用此方法来实现Instrument(插装)的。

    【编辑推荐】


    最新回复(0)