`
冲杯茶喝
  • 浏览: 30604 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JAVA字节码文件操作技巧

 
阅读更多

你知道如何操作JAVA字节码文件吗,这里将介绍与操作Java字节码有关的基本知识和操作Java字节码的方法及Demo,首先我们来看一下AOP的概念,AOP是OOP的延续,是AspectOrientedProgramming的缩写,意思是面向方面编程。

如何操作JAVA字节码文件

本文将介绍与操作Java字节码有关的基本知识和操作Java字节码的方法及Demo,谈到操作Java字节码,不能不谈到AOP(AspectOrientedProgramming),下面来简单介绍一下:

AOP简介

AOP是OOP的延续,是AspectOrientedProgramming的缩写,意思是面向方面编程。AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,AOP可以说也是这种目标的一种实现。

AOP的一个典型应用就是J2EE。J2EE应用系统只有部署在J2EE容器中才能运行,那么为什么划分为J2EE容器和J2EE应用系统?通过对J2EE容器运行机制的分析,可以发现:实际上J2EE容器分离了一般应用系统的一些通用功能,例如事务机制、安全机制以及对象池或线程池等性能优化机制。

这些功能机制是每个应用系统几乎都需要的,因此可以从具体应用系统中分离出来,形成一个通用的框架平台,而且,这些功能机制的设计开发有一定难度,同时运行的稳定性和快速性都非常重要,必须经过长时间调试和运行经验积累而成,因此,形成了专门的J2EE容器服务器产品,如TomcatJBoss。

简单了解AOP后,再来了解一下AOP底层技术:

AOP(AspectOrientedProgramming)底层技术比较

AOP底层技术比较

从上面的图表中分析可以看到,对于一般的操作Java字节码要求(实际上是能够满足笔者100%的要求),综合考虑功能,性能,可用性,易用性,使用Java字节码框架来操作Java字节码是最佳的选择。

下面来了解一下都有哪些开源操作JavaJava字节码的框架:

Javassist;

cglib;

SERP;

Packagegnu.bytecode;

Cojen;

Jdec;

BCEL;

ObjectWebASM;

JClassLib;

TroveClassFileAPI;

Jiapi;

ClassfileReader&Writer;

JBET;

Retroweaver;

Jen;

Soot

这里重点介绍一下ASM,因为下面将使用ASM框架进行Java字节码修改。

ASM这个Java字节码操控框架能被用来动态生成类或者增强既有类的功能。ASM可以直接产生二进制class文件,也可以在类被加载入Java虚拟机之前动态改变类行为。Javaclass被存储在严格格式定义的.class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及Java字节码(指令)。ASM从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。下图对当前接触常用的操作Java字节码框架进行了一个比较:

操作Java字节码框架比较 

ASM的几个特性:

1.JAVABased.

ASM是基于JAVA的,即用JAVA实现的。

2.Visitor模式.

对于ASM来说,Javaclass被描述为一棵树;使用“Visitor”模式遍历整个二进制结构。

3.复杂性低.易学易用.

ASM提供了更为现代的编程模型,降低了操作Java字节码的复杂性,使用事件驱动的处理方式使得用户只需要关注于对其编程有意义的部分,而不必了解Java类文件格式的所有细节:ASM框架提供了默认的“responsetaker”处理这一切。

4.较高的性能

对Java字节码进行操作的同时尽量减小的性能的损失(性能的损失是不可避免)。

这里来介绍一下ASM组成及顺序图:

ASM组成及顺序图


Corepackage提供了一个读写、修改Javabytecode的API,并且为其它的package定义了依据。这个package对于生成Javabytecode、实现大多数的bytecode变换而言意义重大。

Treepackage提供了Javabytecode的内存表示法。

Analysispackage提供了基本的数据流分析和类型检查算法,它们将用于在treeoackage中存储Java方法bytecode。

Commonspackage(包含在ASM2.0中)提供了一些常用的bytecode转换和用于简化bytecode生成的适配器。

Utilpackage包含了一些帮助类和简单的bytecode验证器,它们将有助于开发或者测试。

XMLpackage提供了一个用于在bytecode和XML之间进行转换的适配器,和一些允许使用XSLT定义bytecode转换的兼容SAX的适配器。

顺序图:

ASM顺序图 

Demo

这里我们来实现这样一个功能:在不能改变原代码功能的前提下,对于一个特定类的特定方法有没有被测试过,以HelloTaobao类中方法helloHeyun为例。

类HelloTaobao:

  1. publicclassHelloTaobao  
  2. {  
  3. publicvoidhelloHeyun()  
  4. {  
  5. System.out.println(“Hello,ThisisHeyun’sinvestigationaboutcodecoverage!”);  
  6. }  
  7. }  
  8.  

主方法类:

  1. publicclassMain  
  2. {  
  3. publicstaticvoidmain(String[]args)  
  4. {  
  5. HelloTaobaoht=newHelloTaobao();  
  6. ht.heyunHeyun();  
  7. }  
  8. }  
  9.  

到这里,我们运行一下程序,会在Console输出字符串:“Hello,ThisisHeyun’sinvestigationaboutcodecoverage!”。

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

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

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

  1. publicclassGenerator  
  2. {  
  3. publicstaticvoidmain(String[]args)throwsException  
  4. {  
  5. ClassReadercr=newClassReader(“HellTaobao”);  
  6.  
  7. ClassWritercw=newClassWriter(ClassWriter.COMPUTE_MAXS);  
  8.  
  9. ClassAdapterclassAdapter=newByteCodeClassHandler(cw);  
  10.  
  11. cr.accept(classAdapter,ClassReader.SKIP_DEBUG);  
  12.  
  13. byte[]data=cw.toByteArray();  
  14.  
  15. Filefile=newFile(“HellTaobao.class”);  
  16.  
  17. FileOutputStreamfout=newFileOutputStream(file);  
  18.  
  19. fout.write(data);  
  20.  
  21. fout.close();  
  22. }  
  23. }  
  24.  

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

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

  1. publicclassByteCodeClassHandlerextendsClassAdapter  
  2. {  
  3. publicByteCodeClassHandler(ClassVisitorcv)  
  4. {  
  5. super(cv);  
  6. }  
  7. publicvoidvisit(intversion,intaccess,Stringname,Stringsignature,  
  8. StringsuperName,String[]interfaces)  
  9. {  
  10. super.visit(version,access,name,signature,superName,interfaces);  
  11. }  
  12. publicvoidvisitSource(Stringsource,Stringdebug)  
  13. {  
  14. super.visitSource(source,debug);  
  15.  
  16. }  
  17. publicvoidvisitEnd()  
  18. {  
  19. }  
  20.  
  21. @Override  
  22.  
  23. publicMethodVisitorvisitMethod(intaccess,Stringname,Stringdesc,  
  24.  
  25. Stringsignature,String[]exceptions)  
  26. {  
  27. MethodVisitormv=cv.visitMethod(access,name,desc,signature,  
  28.  
  29. exceptions);  
  30.  
  31. MethodVisitorwrappedMv=mv;  
  32.  
  33. if(mv!=null)  
  34.  
  35. {  
  36.  
  37. //对于”helloHeyun”方法进行改造  
  38.  
  39. if(name.equals(“helloHeyun”))  
  40. {  
  41.  
  42. //使用自定义MethodVisitor,改写方法内容  
  43.  
  44. wrappedMv=newByteCodeMethodHandler(mv);  
  45. }  
  46. }  
  47. returnwrappedMv;  
  48. }  
  49. }  
  50.  

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

  1. publicclassByteCodeMethodHandlerextendsMethodAdapter  
  2. {  
  3. publicByteCodeMethodHandler(MethodVisitormv)  
  4. {  
  5. super(mv);  
  6. }  
  7. publicvoidvisitCode()  
  8. {  
  9. visitMethodInsn(Opcodes.INVOKESTATIC,“ControlByteCode”,  
  10.  
  11. “controlByteCodeByHeyun”,“()V”);  
  12. }  
  13. }  
  14.  

6.ControlByteCode类的controlByteCodeByHeyun方法如下

  1. publicclassControlByteCode  
  2. {  
  3. publicstaticvoidcontrolByteCodeByHeyun()  
  4. {  
  5. System.out.println(“Thismethodhasalreadybeencovered.”);  
  6.  
  7. //TODOrealsecuritycheck  
  8. }  
  9. }  

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

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

  1. Hello,ThisisHeyun’sinvestigationaboutcodecoverage!  
  2.  
  3. Thismethodhasalreadybeencovered.  

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

 

最后交代下那些框架应用了ASM:

CGLIB and ASM

 

FROM:http://developer.51cto.com/art/201009/227243_2.htm

分享到:
评论

相关推荐

    java源码:JAVA字节码操作库 BCEL.zip

    Java字节码操作库BCEL(Byte Code Engineering Library)是一个强大的工具,用于分析、修改和创建Java类文件。它是Apache软件基金会的Jakarta项目的一部分,为开发者提供了对字节码的底层控制,使得开发者能够在运行...

    Recaf一个现代Java字节码编辑器

    **Recaf:现代Java字节码编辑器** 在Java开发领域,字节码编辑器是一种不可或缺的工具,...在实际使用中,配合其提供的文档和社区资源,开发者可以更深入地掌握Java字节码操作的技巧,提升开发效率和解决问题的能力。

    该项目主要是JAVA字节码的学习项目.zip

    3. **字节码指令集**:Java字节码指令集包括许多单字节或双字节的指令,如`aload_0`(加载局部变量0到操作数栈)、`iconst_1`(将整数1压入操作数栈)等。这些指令控制程序的流程,进行数据处理。 4. **字节码优化*...

    从Java代码到字节码(1)Java开发Java经验技巧共

    本资源“从Java代码到字节码(1)Java开发Java经验技巧共41页.pdf.zip”是一个关于Java开发的教程,旨在帮助开发者深入理解Java程序的生命周期,特别是从源代码编译成字节码的过程,这是Java平台的关键特性之一。...

    基于Java字节码增强技术实现的协程Demo.zip

    Java字节码增强技术是Java开发中的一种高级技巧,它允许开发者在程序运行时动态修改类的字节码,从而实现一些特殊的功能,比如AOP(面向切面编程)、性能监控、事务管理等。协程是一种轻量级的线程,它在执行过程中...

    java字节码例子 可以动态修改类 bcel

    Java字节码是Java虚拟机(JVM)执行的二进制代码,它构成了Java程序的基础。在Java中,源代码被编译成字节码,然后由JVM解释执行。这种设计使得Java具有跨平台的特性,因为字节码在任何支持JVM的平台上都可以运行。`...

    2021-2022年收藏的精品资料软件工程师Java字节码开发深入解析教程解释.docx

    总结来说,Java字节码是JVM执行的基础,理解和掌握字节码能够帮助我们更好地理解JVM的工作原理,优化代码性能,并利用反射机制实现高级编程技巧。通过`javap`等工具,开发者可以深入到程序的底层,进一步提升编程...

    Java虚拟机字节码.zip

    1. **ASM框架**: ASM是一个Java字节码操控和分析框架,常用于动态代理、AOP(面向切面编程)和代码生成。通过ASM,程序员可以直接操作字节码,生成和转换Java类。ASM提供了一套详细的API,允许开发人员在字节码级别...

    Android字节码插桩

    5. **加载并运行**:将生成的新字节码文件加载到Dalvik VM或者ART中,应用运行时会执行这些修改过的字节码。 在"plugin-master"这个项目中,可能包含了一个关于如何使用ASM进行Android字节码插桩的示例或者教程。...

    java修改class文件工具jbe

    5. **字节码操作技巧**:使用 JBE 进行字节码操作时,需要注意保持字节码的合法性和平衡性,因为错误的修改可能导致程序无法运行。此外,修改后的字节码可能需要重新签名,尤其是当涉及到类加载器或安全权限时。 6....

    HelloWorld的javap -verbose HelloWorld 字节码初探

    1. **Java字节码**:解释字节码的构成,包括常量池、操作码、操作数、异常表等组成部分,以及它们如何协同工作以执行Java程序。 2. **javap工具的使用**:详细介绍如何使用`javap`命令,包括基础用法和`-verbose`等...

    ASM 字节码修改工具中文帮助手册

    - **指引**: 给出了使用 ASM 进行字节码操作的最佳实践和技巧。 - **性能**: 讨论了 ASM 在不同场景下的性能表现,以及如何优化其性能。 综上所述,ASM 4.0 是一个强大且灵活的 Java 字节码操作框架,提供了丰富的...

    基于 javaagent 对 java 原生类的 方法进行字节码动态修改, 以此引发的一些关于 绕过 Java 软件.zip

    `Instrumentation` 接口是与 javaagent 交互的关键,它提供了添加、移除类文件转换器(ClassFileTransformer)的方法,这些转换器可以改变字节码。 对于原生类,也就是包含 native 方法的类,它们的字节码处理有...

    java计算器程序,该计算器程序能够直接运行,因为已经编译好了字节码

    这个程序已经完成了编译过程,产生了字节码文件,使得用户可以直接运行而无需额外的编译步骤。字节码是Java虚拟机(JVM)能理解的一种中间语言,它使得Java程序具有“一次编写,到处运行”的跨平台特性。 在Java...

    cpp-ToyJVM用C编写的实验性Java字节解释器

    通过研究和实践ToyJVM,开发者不仅可以提升C语言编程技巧,还能深入了解Java字节码的执行流程,这对于优化Java代码、调试问题以及设计高性能的Java应用都有着极大的帮助。总的来说,这个项目提供了一个独特的视角,...

    Java逆向工程-附简单操作指南.zip

    在Java环境中,由于Java字节码的存在,逆向工程通常涉及到对Class文件的理解和解析。工具有如JD-GUI、JAD和 FernFlower 等可以帮助开发者查看和理解Java字节码。 文档"新手请看-老手无视.docx"很可能是针对Java逆向...

    JAVA反编译软件(可将class文件反编译为java文件)

    Java反编译是将Java字节码(`.class`文件)转换回源代码(`.java`文件)的过程。Java字节码是一种中间语言,由JVM(Java虚拟机)执行,而反编译就是尝试将这种二进制形式还原成人类可读的代码。 2. **Java反编译的...

    Android中修改运行时内存Dalvik字节码.rar

    与Java字节码不同,Dalvik字节码是专门为Android设计的,它在设备上被即时编译(JIT)或提前编译(AOT),如ART(Android RunTime)环境,以提高执行效率。 在Android系统中,修改运行时内存中的Dalvik字节码通常...

    bytecode:使用 Java 字节码进行测试

    Java字节码是Java平台的核心特性之一,它在软件开发中扮演着至关重要的角色。字节码是一种中间语言,它是Java源代码经过编译后生成的二进制代码,以.class文件的形式存在。这种设计使得Java程序具有了跨平台的能力,...

    Java反编译工具,将class文件反编译成Java文件

    Java字节码是平台无关的中间语言,它由JVM(Java虚拟机)执行。反编译工具通过解析字节码结构,将其转换回相应的Java语法。由于字节码不包含原始的变量名、注释和某些特定的代码结构,因此反编译的结果可能与原始源...

Global site tag (gtag.js) - Google Analytics