- http://developer.51cto.com 2010-09-25 10:20 admin qa.taobao.com 我要评论(0)
- 本文将介绍与操作Java字节码有关的基本知识和操作Java字节码的方法及Demo,谈到操作Java字节码,不能不谈到AOP,这里向大家做一下简单介绍。
下面我们来操作一下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(插装)的。
【编辑推荐】