Skip to content

Latest commit

 

History

History
247 lines (179 loc) · 12.9 KB

README.md

File metadata and controls

247 lines (179 loc) · 12.9 KB

Learn Java ASM

Gitee Github GitHub GitHub stars GitHub forks GitHub issues GitHub last commit

🍁 Java ASM is an open-source java library for manipulating bytecode.

本项目旨在系统地介绍如何学习Java ASM的知识,主要涉及Core API、OPCODE和Tree API等内容。至于学习的预期目标就是,用一个形象的说法来讲,让字节码在你的手中“跳舞”:看看你的左手,一个完整的ClassFile拆解成不同粒度的字节码内容;看看你的右手,不同粒度的字节码内容又重新组织成一个ClassFile结构。

           _______                                 ,        _        _        
          (,     /'                              /'/      /' `\     ' )     _)
               /'                              /' /     /'   ._)    //  _/~/' 
             /'____ .     ,   ____          ,/'  /     (____      /'/_/~ /'   
   _       /'/'    )|    /  /'    )        /`--,/           )   /' /~  /'     
 /' `    /'/'    /' |  /' /'    /'       /'    /          /'  /'     /'       
(_____,/' (___,/(___|/(__(___,/(__   (,/'     (_,(_____,/'(,/'      (_,       

如果我们学会了Java ASM之后,可能还是需要一个具体的应用场景来进行使用,这个场景就是由 Java Agent 开启的。

那么,Java ASM和Java Agent这两者之间是什么关系呢? Java ASM是一个操作字节码的工具(tool),而Java Agent提供了修改字节码的机会(opportunity)。 想像这样一个场景: 有一个JVM正在运行,突然Java Agent在JVM上打开一扇大门,Java ASM通过大门冲进JVM里面,就要开始修改字节码了。

.class --- Java ASM --- Java Agent --- JVM

再打个比方,Java ASM就是“一匹千里马”,而Java Agent就是“伯乐”。 如果遇不到“伯乐”,可能“千里马”的才能就埋没了;正因为有了“伯乐”,“千里马”就有了施展才能的机会。

世有伯乐,然后有千里马。
千里马常有,而伯乐不常有。
故虽有名马,祗辱于奴隶人之手,骈死于槽枥之间,不以千里称也。

1. 如何使用

1.1 代码下载

Gitee Github

Gitee 仓库下载代码,使用如下命令:

git clone https://gitee.com/lsieun/learn-java-asm

GitHub 仓库下载代码,使用如下命令:

git clone https://github.com/lsieun/learn-java-asm

1.2 开发环境

Licence Git Java Apache Maven IntelliJ IDEA

learn-java-asm项目当中,使用的ASM版本为9.0。如果想使用最新Maven Central 版本,可以修改pom.xml文件中的asm.version属性:

<asm.version>9.0</asm.version>

1.3. 运行代码

learn-java-asm项目当中,包含main方法的类主要位于run包(src/main/java/run)。

2. 课程资料

51cto Bilibili lsieun.github.io

2.1. ASM的组成部分

从组成结构上来说,Java ASM有Core API和Tree API两部分组成。

                                   ┌─── asm.jar
                                   │
            ┌─── Core API ─────────┼─── asm-util.jar
            │                      │
            │                      └─── asm-commons.jar
Java ASM ───┤
            │
            │                      ┌─── asm-tree.jar
            └─── Tree API ─────────┤
                                   └─── asm-analysis.jar

从依赖关系角度上说,Java ASM当中的各个.jar之间的依赖关系如下:

┌────────────────────────────┬─────────────────────────────┐
│                    ┌───────┴────────┐                    │
│     util           │    analysis    │         commons    │
│             ┌──────┴────────────────┴──────┐             │
│             │             tree             │             │
├─────────────┴──────────────────────────────┴─────────────┤
│                           core                           │
└──────────────────────────────────────────────────────────┘

2.2. ASM能够做什么

从应用的角度来说,Java ASM可以进行Class Generation、Class Transformation和Class Analysis三个类型的操作。

                                   ┌─── find potential bugs
                                   │
            ┌─── analysis ─────────┼─── detect unused code
            │                      │
            │                      └─── reverse engineer code
            │
Java ASM ───┼─── generation
            │
            │                      ┌─── optimize programs
            │                      │
            └─── transformation ───┼─── obfuscate programs
                                   │
                                   └─── insert performance monitoring code

2.3. top, null和void

在下表当中,top、null和void三者相对应的转换值:

┌─────────────┬────────────────────────────┬────────────────────────────────┐
│   .class    │          ASM Type          │      ASM Value in Frame        │
├─────────────┼────────────────────────────┼────────────────────────────────┤
│     top     │            null            │ BasicValue.UNINITIALIZED_VALUE │
├─────────────┼────────────────────────────┼────────────────────────────────┤
│ aconst_null │ BasicInterpreter.NULL_TYPE │   BasicValue.REFERENCE_VALUE   │
├─────────────┼────────────────────────────┼────────────────────────────────┤
│    void     │       Type.VOID_TYPE       │              null              │
└─────────────┴────────────────────────────┴────────────────────────────────┘

3. 注意事项

3.1. 添加typo字典

在编写代码的过程中,会遇到一些Typo提示,原因是insn等内容不是合法的单词。

解决方法:借助于IntelliJ IDEA的Spellchecking 的功能。

操作步骤:

  • 第一步,在Settings/Preferences当中,找到Editor | Natural Languages | Spelling位置。
  • 第二步,在右侧的Custom dictionaries位置,添加custom dictionary,在learn-java-asm项目根目录下,有一个accepted-words.dic文件,添加该文件即可。

配置完成之后,需要重新启动IntelliJ IDEA才能生效。

3.2. 查看笔记

在编写代码的过程中,为了方便理解代码,我添加了一些笔记,格式如下:

NOTE: 希望这是一条有用的笔记

但是,在默认情况下,它并不会高亮显示,因此不容易被察觉到。

解决方法:借助于IntelliJ IDEA的TODO comments 功能。

操作步骤:

  • 第一步,在Settings/Preferences当中,找到Editor | TODO位置。
  • 第二步,在右侧的Patterns位置,添加以下内容:
\bnote\b.*

配置完成之后,需要重新启动IntelliJ IDEA才能生效。

3.3. 关闭调试信息

在默认情况下,运行任何类,都会输出调试信息。在调试信息中,会带有[DEBUG]标识。

如果想关闭调试信息,可以修改lsieun.cst.Const类的DEBUG字段值为false(默认值为true):

public class Const {
    public static final boolean DEBUG = false;
}

然后,执行mvn clean compile对类进行重新编译:

mvn clean compile

等待编译完成之后,再次运行程序。

4. 交流反馈

  • 如果您有好的想法,可以提issues
  • 如果您想贡献代码,可以进行fork
  • 如果您有其它问题,可以添加QQ群(参考联系方式)

5. 联系方式

wechat Tencent QQ QQ Group Java字节码交流QQ群

6. License

This project is licensed under the MIT License. See the LICENSE file for the full license text.