Full Code of lsieun/learn-java-asm for AI

main a8b6328a3207 cached
231 files
615.8 KB
150.2k tokens
1337 symbols
1 requests
Download .txt
Showing preview only (698K chars total). Download the full file or copy to clipboard to get everything.
Repository: lsieun/learn-java-asm
Branch: main
Commit: a8b6328a3207
Files: 231
Total size: 615.8 KB

Directory structure:
gitextract_4n4clgmd/

├── .gitignore
├── LICENSE
├── README.md
├── accepted-words.dic
├── pom.xml
└── src/
    └── main/
        └── java/
            ├── lsieun/
            │   ├── annotation/
            │   │   └── todo/
            │   │       └── ToDo.java
            │   ├── asm/
            │   │   ├── analysis/
            │   │   │   ├── ControlFlowAnalyzer.java
            │   │   │   ├── ControlFlowAnalyzer2.java
            │   │   │   ├── ControlFlowEdgeAnalyzer.java
            │   │   │   ├── ControlFlowEdgeAnalyzer2.java
            │   │   │   ├── ControlFlowGraphAnalyzer.java
            │   │   │   ├── DataFlowAnalyzer.java
            │   │   │   ├── InsnText.java
            │   │   │   ├── MockAnalyzer.java
            │   │   │   ├── RemoveDeadCodeNode.java
            │   │   │   ├── RemoveDeadCodeVisitor.java
            │   │   │   ├── RemoveUnusedCastNode.java
            │   │   │   ├── RemoveUnusedCastVisitor.java
            │   │   │   ├── cc/
            │   │   │   │   ├── CyclomaticComplexity.java
            │   │   │   │   ├── CyclomaticComplexityAnalyzer.java
            │   │   │   │   └── CyclomaticComplexityFrame.java
            │   │   │   ├── cfg/
            │   │   │   │   ├── ControlFlowBuilder.java
            │   │   │   │   ├── ControlFlowGraph.java
            │   │   │   │   ├── Edge.java
            │   │   │   │   ├── EdgeCreator.java
            │   │   │   │   ├── FramelessAnalyzer.java
            │   │   │   │   └── SimpleEdgeCreator.java
            │   │   │   ├── diagnosis/
            │   │   │   │   ├── DeadCodeDiagnosis.java
            │   │   │   │   ├── NullDereferenceDiagnosis.java
            │   │   │   │   ├── NullabilityDiagnosis.java
            │   │   │   │   ├── RedundantVariableDiagnosis.java
            │   │   │   │   ├── RelatedInstructionDiagnosis.java
            │   │   │   │   └── ReverseEngineerMethodArgumentsDiagnosis.java
            │   │   │   ├── graph/
            │   │   │   │   ├── InsnBlock.java
            │   │   │   │   ├── TextBox.java
            │   │   │   │   └── TextGraph.java
            │   │   │   ├── nullability/
            │   │   │   │   ├── NullDeferenceInterpreter.java
            │   │   │   │   ├── Nullability.java
            │   │   │   │   ├── NullabilityAnalyzer.java
            │   │   │   │   ├── NullabilityFrame.java
            │   │   │   │   ├── NullabilityInterpreter.java
            │   │   │   │   └── NullabilityValue.java
            │   │   │   ├── state/
            │   │   │   │   ├── StateInterpreter.java
            │   │   │   │   ├── StateType.java
            │   │   │   │   └── StateValue.java
            │   │   │   └── transition/
            │   │   │       └── DestinationInterpreter.java
            │   │   ├── commons/
            │   │   │   ├── ClassRemapperExample01.java
            │   │   │   ├── ClassRemapperExample02.java
            │   │   │   ├── ClassRemapperExample03.java
            │   │   │   ├── GeneratorAdapterExample01.java
            │   │   │   ├── InstructionAdapterExample01.java
            │   │   │   ├── MethodStackMapFrame02Visitor.java
            │   │   │   ├── MethodStackMapFrameVisitor.java
            │   │   │   ├── SerialVersionUIDAdderExample01.java
            │   │   │   └── StaticInitMergerExample01.java
            │   │   ├── core/
            │   │   │   ├── ChangeURLVisitor.java
            │   │   │   ├── ClassChangeVersionVisitor.java
            │   │   │   ├── ClassCloneVisitor.java
            │   │   │   ├── ClassDecompileVisitor.java
            │   │   │   ├── ClassListMemberVisitor.java
            │   │   │   ├── ClassRemoveAttributeVisitor.java
            │   │   │   ├── MethodAroundVisitor.java
            │   │   │   ├── MethodAroundVisitor2.java
            │   │   │   ├── MethodEmptyBodyVisitor.java
            │   │   │   ├── MethodEnterVisitor.java
            │   │   │   ├── MethodExitVisitor.java
            │   │   │   ├── MethodFindInvokeVisitor.java
            │   │   │   ├── MethodFindRefVisitor.java
            │   │   │   ├── MethodParameterVisitor.java
            │   │   │   ├── MethodParameterVisitor2.java
            │   │   │   ├── MethodPatternAdapter.java
            │   │   │   ├── MethodRemoveAddZeroVisitor.java
            │   │   │   ├── MethodRemoveGetFieldPutFieldVisitor.java
            │   │   │   ├── MethodRemoveNopVisitor.java
            │   │   │   ├── MethodRemovePrintVisitor.java
            │   │   │   ├── MethodReplaceInvokeVisitor.java
            │   │   │   ├── MethodTimerVisitor.java
            │   │   │   ├── MethodTimerVisitor2.java
            │   │   │   ├── MethodTimerVisitor3.java
            │   │   │   ├── MethodTimerVisitor4.java
            │   │   │   ├── SuperPackageAttribute.java
            │   │   │   ├── counter/
            │   │   │   │   ├── ClassCounterVisitor.java
            │   │   │   │   └── MethodCounterAdapter.java
            │   │   │   ├── empty/
            │   │   │   │   ├── EmptyAnnotationVisitor.java
            │   │   │   │   ├── EmptyClassVisitor.java
            │   │   │   │   ├── EmptyFieldVisitor.java
            │   │   │   │   ├── EmptyMethodVisitor.java
            │   │   │   │   ├── EmptyModuleVisitor.java
            │   │   │   │   └── EmptyRecordComponentVisitor.java
            │   │   │   ├── info/
            │   │   │   │   ├── InfoClassVisitor.java
            │   │   │   │   ├── InfoFieldVisitor.java
            │   │   │   │   └── InfoMethodVisitor.java
            │   │   │   └── timer/
            │   │   │       ├── ClassTimerVisitor.java
            │   │   │       └── MethodTimerAdapter.java
            │   │   ├── template/
            │   │   │   ├── CheckMethodAnnotationVisitor.java
            │   │   │   ├── ClassAddAnnotationVisitor.java
            │   │   │   ├── ClassAddCustomAttributeVisitor.java
            │   │   │   ├── ClassAddFieldVisitor.java
            │   │   │   ├── ClassAddInterfaceVisitor.java
            │   │   │   ├── ClassAddMethodVisitor.java
            │   │   │   ├── ClassGetAttributeContentVisitor.java
            │   │   │   ├── ClassMergeVisitor.java
            │   │   │   ├── ClassMergeVisitorRun.java
            │   │   │   ├── ClassPrintAnnotationVisitor.java
            │   │   │   ├── ClassPrintParameterVisitor.java
            │   │   │   ├── ClassRemoveFieldVisitor.java
            │   │   │   ├── ClassRemoveMethodVisitor.java
            │   │   │   ├── ClassRenameAdapter.java
            │   │   │   ├── ClassRenameAdapterRun.java
            │   │   │   ├── ClassReplaceMethodBodyVisitor.java
            │   │   │   ├── CustomAttribute.java
            │   │   │   ├── FieldAccessAdapter.java
            │   │   │   ├── FieldAccessAdapterRun.java
            │   │   │   ├── FieldAccessConverter.java
            │   │   │   ├── Info.java
            │   │   │   ├── MethodCallAdapter.java
            │   │   │   ├── MethodCallAdapterRun.java
            │   │   │   ├── MethodCallConverter.java
            │   │   │   ├── MethodEnteringAdapter.java
            │   │   │   ├── MethodEnteringVisitor.java
            │   │   │   ├── MethodEnteringVisitorRun.java
            │   │   │   ├── MethodExitingAdapter.java
            │   │   │   ├── MethodExitingAdapterRun.java
            │   │   │   ├── MethodExitingConverter.java
            │   │   │   ├── MethodFinallyAdapter.java
            │   │   │   ├── MethodFinallyAdapterRun.java
            │   │   │   ├── MethodFinallyConverter.java
            │   │   │   ├── MethodPrintInstructionAdapter.java
            │   │   │   ├── MethodPrintInstructionVisitor.java
            │   │   │   ├── MethodWithSameTryCatchLogicVisitor.java
            │   │   │   ├── MethodWithWholeTryCatchVisitor.java
            │   │   │   ├── RefRenameAdapter.java
            │   │   │   └── RemoveSyntheticVisitor.java
            │   │   ├── tree/
            │   │   │   ├── ChangeMemberNameBasedOnAnnotationNode.java
            │   │   │   ├── ChangeThisNode.java
            │   │   │   ├── ClassAddCustomAttributeNode.java
            │   │   │   ├── ClassAddFieldNode.java
            │   │   │   ├── ClassAddMethodNode.java
            │   │   │   ├── ClassAddTimerNode.java
            │   │   │   ├── ClassRemoveFieldNode.java
            │   │   │   ├── ClassRemoveMethodNode.java
            │   │   │   ├── MixCore2TreeVisitor.java
            │   │   │   ├── MixTree2CoreNode.java
            │   │   │   ├── OptimizeJumpNode.java
            │   │   │   ├── RemoveGetFieldPutFieldNode.java
            │   │   │   ├── my/
            │   │   │   │   ├── MyClassNode.java
            │   │   │   │   ├── MyClassVisitor.java
            │   │   │   │   ├── MyMethodAdapter.java
            │   │   │   │   └── MyMethodNode.java
            │   │   │   └── transformer/
            │   │   │       ├── ClassTransformer.java
            │   │   │       └── MethodTransformer.java
            │   │   └── util/
            │   │       ├── CheckClassAdapterExample01Generate.java
            │   │       ├── CheckClassAdapterExample02Generate.java
            │   │       ├── CodeUtils.java
            │   │       ├── TraceClassVisitorExample01Generate.java
            │   │       ├── TraceClassVisitorExample02Transform.java
            │   │       ├── TraceClassVisitorExample03.java
            │   │       └── TreePrinter.java
            │   ├── classfile/
            │   │   ├── CPInfo.java
            │   │   ├── ClassFile.java
            │   │   └── InsnRaw.java
            │   ├── cst/
            │   │   └── Const.java
            │   ├── drawing/
            │   │   ├── canvas/
            │   │   │   ├── Box.java
            │   │   │   ├── Canvas.java
            │   │   │   ├── Drawable.java
            │   │   │   ├── TextAlign.java
            │   │   │   ├── TextDirection.java
            │   │   │   └── TextPixel.java
            │   │   └── theme/
            │   │       ├── line/
            │   │       │   └── ContinuousLine.java
            │   │       ├── shape/
            │   │       │   ├── Rectangle.java
            │   │       │   └── RectangleWithText.java
            │   │       ├── table/
            │   │       │   ├── AbstractTable.java
            │   │       │   ├── FixedWidthOneLineTable.java
            │   │       │   └── OneLineTable.java
            │   │       └── text/
            │   │           └── PlainText.java
            │   ├── trove/
            │   │   ├── HashFunctions.java
            │   │   ├── PrimeFinder.java
            │   │   ├── THash.java
            │   │   ├── TIntArrayList.java
            │   │   ├── TIntFunction.java
            │   │   ├── TIntHash.java
            │   │   ├── TIntHashingStrategy.java
            │   │   ├── TIntIntHashMap.java
            │   │   ├── TIntIntIterator.java
            │   │   ├── TIntIntProcedure.java
            │   │   ├── TIntProcedure.java
            │   │   ├── TIterator.java
            │   │   ├── TPrimitiveHash.java
            │   │   ├── TPrimitiveIterator.java
            │   │   └── package-info.java
            │   └── utils/
            │       ├── ASMUtilsCore.java
            │       ├── ASMUtilsTree.java
            │       ├── BoxDrawingUtils.java
            │       ├── ByteArrayClassLoader.java
            │       ├── ByteUtils.java
            │       ├── DescriptorUtils.java
            │       ├── FileUtils.java
            │       ├── FrameUtils.java
            │       ├── HexFormat.java
            │       ├── HexUtils.java
            │       ├── IOUtils.java
            │       ├── JarUtils.java
            │       ├── OpcodeConst.java
            │       ├── ReadUtils.java
            │       ├── StringUtils.java
            │       └── ValueUtils.java
            ├── run/
            │   ├── ASMPrint.java
            │   ├── BoxDrawingRun.java
            │   ├── BytecodeRun.java
            │   ├── ControlFlowGraphRun.java
            │   ├── ControlFlowGraphType.java
            │   ├── HelloWorldAnalysisCore.java
            │   ├── HelloWorldAnalysisTree.java
            │   ├── HelloWorldFrameCore.java
            │   ├── HelloWorldFrameCore02.java
            │   ├── HelloWorldFrameTree.java
            │   ├── HelloWorldGenerateCore.java
            │   ├── HelloWorldGenerateTree.java
            │   ├── HelloWorldRun.java
            │   ├── HelloWorldTransformCore.java
            │   ├── HelloWorldTransformTree.java
            │   ├── MockAnalyzerRun.java
            │   ├── PrintASMCodeCore.java
            │   ├── PrintASMCodeTree.java
            │   ├── PrintASMTextClass.java
            │   ├── PrintASMTextLambda.java
            │   ├── PrintOpcodeTable.java
            │   └── jar/
            │       ├── CompareTwoJarFile.java
            │       └── FindJarClassItem.java
            └── sample/
                ├── HelloWorld.java
                └── ParameterUtils.java

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

# IDEA

.idea/
*.iml
*.kotlin_module
target/
lib/
build/
dist/
.*
*.data
!.gitignore


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020 lsieun

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Learn Java ASM

[![Gitee](https://img.shields.io/badge/Gitee-white.svg?style=flat-square&logo=gitee&logoColor=C71D23)](https://gitee.com/lsieun/learn-java-asm)
[![Github](https://img.shields.io/badge/GitHub-white.svg?style=flat-square&logo=github&logoColor=181717)](https://github.com/lsieun/learn-java-asm)
![GitHub](https://img.shields.io/github/license/lsieun/learn-java-asm)
![GitHub stars](https://img.shields.io/github/stars/lsieun/learn-java-asm.svg)
![GitHub forks](https://img.shields.io/github/forks/lsieun/learn-java-asm.svg)
![GitHub issues](https://img.shields.io/github/issues-raw/lsieun/learn-java-asm?label=issues)
![GitHub last commit](https://img.shields.io/github/last-commit/lsieun/learn-java-asm.svg)

:maple_leaf: Java [ASM](https://asm.ow2.io/) is an open-source java library for manipulating bytecode.

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

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

---

如果我们学会了Java ASM之后,可能还是需要一个具体的应用场景来进行使用,
这个场景就是由 [Java Agent](https://docs.oracle.com/en/java/javase/25/docs/api/java.instrument/java/lang/instrument/Instrumentation.html) 开启的。

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

```text
.class --- Java ASM --- Java Agent --- JVM
```

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

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

---

## 1. 如何使用

### 1.1 代码下载

[![Gitee](https://img.shields.io/badge/Gitee-white.svg?style=flat-square&logo=gitee&logoColor=C71D23)](https://gitee.com/lsieun/learn-java-asm)
[![Github](https://img.shields.io/badge/GitHub-white.svg?style=flat-square&logo=github&logoColor=181717)](https://github.com/lsieun/learn-java-asm)

从[Gitee](https://gitee.com/lsieun/learn-java-asm) 仓库下载代码,使用如下命令:

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

从[GitHub](https://github.com/lsieun/learn-java-asm) 仓库下载代码,使用如下命令:

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

### 1.2 开发环境

[![Licence](https://img.shields.io/github/license/lsieun/learn-java-asm?style=social)](./LICENSE)
![Git](https://img.shields.io/badge/Git-white.svg?style=flat-square&logo=git&logoColor=F05032)
![Java](https://img.shields.io/badge/-Java-white.svg?style=flat-square&logo=java&logoColor=007396)
![Apache Maven](https://img.shields.io/badge/Maven-white.svg?style=flat-square&logo=Apache%20Maven&logoColor=C71A36)
![IntelliJ IDEA](https://img.shields.io/badge/IntelliJ_IDEA-white.svg?style=flat-square&logo=intellij-idea&logoColor=000000)

- [Git](https://git-scm.com/)
- [Java 8](https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html)
- [Apache Maven](https://maven.apache.org/)
- [IntelliJ IDEA](https://www.jetbrains.com/idea/download/other.html) (Ultimate or Community Edition)

在`learn-java-asm`项目当中,使用的ASM版本为`9.0`。如果想使用最新![Maven Central](https://img.shields.io/maven-central/v/org.ow2.asm/asm.svg?color=25a162&label=ASM) 版本,可以修改`pom.xml`文件中的`asm.version`属性:

```text
<asm.version>9.0</asm.version>
```

### 1.3. 运行代码

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

## 2. 课程资料

[![51cto](https://img.shields.io/website/https/edu.51cto.com.svg?label=51cto)](https://edu.51cto.com/lecturer/9210464.html)
[![Bilibili](https://img.shields.io/website/https/bilibili.com.svg?label=bilibili&style=flat-square&logo=bilibili&logoColor=00A1D6)](https://space.bilibili.com/1321054247)
[![lsieun.github.io](https://img.shields.io/website/https/lsieun.github.io.svg?label=lsieun.github.io)](https://lsieun.github.io)

- 《Java ASM系列一:Core API》
  - 文章地址: [lsieun.github.io](https://lsieun.github.io/java/asm/java-asm-season-01.html) | [51CTO](https://blog.51cto.com/lsieun/2924583)
  - 视频地址: [51CTO](https://edu.51cto.com/course/28517.html) | [Bilibili](https://space.bilibili.com/1321054247/channel/seriesdetail?sid=381716)
- 《Java ASM系列二:OPCODE》
  - 文章地址:[lsieun.github.io](https://lsieun.github.io/java/asm/java-asm-season-02.html) | [51CTO](https://blog.51cto.com/lsieun/3273965)
  - 视频地址:[51CTO](https://edu.51cto.com/course/28870.html) | [Bilibili](https://space.bilibili.com/1321054247/channel/seriesdetail?sid=381716)
- 《Java ASM系列三:Tree API》
  - 文章地址:[lsieun.github.io](https://lsieun.github.io/java/asm/java-asm-season-03.html) | [51CTO](https://blog.51cto.com/lsieun/4034588)
  - 视频地址:[51CTO](https://edu.51cto.com/course/29459.html) | [Bilibili](https://space.bilibili.com/1321054247/channel/seriesdetail?sid=381716)

### 2.1. ASM的组成部分

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

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

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

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

### 2.2. ASM能够做什么

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

```text
                                   ┌─── 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三者相对应的转换值:

```text
┌─────────────┬────────────────────────────┬────────────────────────────────┐
│   .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](https://www.jetbrains.com/help/idea/spellchecking.html) 的功能。

操作步骤:

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

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

### 3.2. 查看笔记

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

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

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

解决方法:借助于IntelliJ IDEA的[TODO comments](https://www.jetbrains.com/help/idea/using-todo.html) 功能。

操作步骤:

- 第一步,在`Settings/Preferences`当中,找到`Editor | TODO`位置。
- 第二步,在右侧的Patterns位置,添加以下内容:

```text
\bnote\b.*
```

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

### 3.3. 关闭调试信息

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

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

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

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

```text
mvn clean compile
```

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

## 4. 交流反馈

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

## 5. 联系方式

[![wechat](https://img.shields.io/badge/-lsieun-white.svg?style=flat-square&logo=wechat&logoColor=07C160)](https://lsieun.github.io/assets/images/contact/we-chat.jpg)
[![Tencent QQ](https://img.shields.io/badge/515882294-white.svg?style=flat-square&logo=tencentqq&logoColor=EB1923)](https://lsieun.github.io/assets/images/contact/qq.png)
[![QQ Group](https://img.shields.io/badge/584642776-white.svg?style=flat-square&logo=tencentqq&logoColor=1DA1F2&label=QQ%20Group)](https://lsieun.github.io/assets/images/contact/qq-group.jpg)
[![Java字节码交流QQ群](https://pub.idqqimg.com/wpa/images/group.png)](https://jq.qq.com/?_wv=1027&k=yOBiOaJV)

## 6. License

This project is licensed under the MIT License.
See the [LICENSE](./LICENSE) file for the full license text.


================================================
FILE: accepted-words.dic
================================================
bilibili
gitee
insn
lsieun


================================================
FILE: pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>lsieun</groupId>
    <artifactId>learn-java-asm</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <!-- Resource -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

        <!-- JDK -->
        <java.version>1.8</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <asm.version>9.9.1</asm.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm</artifactId>
            <version>${asm.version}</version>
        </dependency>
        <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm-commons</artifactId>
            <version>${asm.version}</version>
        </dependency>
        <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm-util</artifactId>
            <version>${asm.version}</version>
        </dependency>
        <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm-tree</artifactId>
            <version>${asm.version}</version>
        </dependency>
        <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm-analysis</artifactId>
            <version>${asm.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Java Compiler -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <fork>true</fork>
                    <compilerArgs>
                        <arg>-g</arg>
                        <arg>-parameters</arg>
                    </compilerArgs>
                </configuration>
            </plugin>

            <!-- 生成 source code 的 JAR 包 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>3.3.1</version>
                <executions>
                    <execution>
                        <id>default-source-jar</id>
                        <phase>package</phase>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

================================================
FILE: src/main/java/lsieun/annotation/todo/ToDo.java
================================================
package lsieun.annotation.todo;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;

@Retention(RetentionPolicy.SOURCE)
@Target({
        TYPE,
        FIELD,
        CONSTRUCTOR,
        METHOD,
        PARAMETER,
        LOCAL_VARIABLE,
        ANNOTATION_TYPE,
        PACKAGE,
        TYPE_PARAMETER,
        TYPE_USE,
//        MODULE,
//        RECORD_COMPONENT,
})
public @interface ToDo {
    String[] value();
}

================================================
FILE: src/main/java/lsieun/asm/analysis/ControlFlowAnalyzer.java
================================================
package lsieun.asm.analysis;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.analysis.AnalyzerException;

import java.util.ArrayList;
import java.util.List;

/**
 * 将 {@link org.objectweb.asm.tree.analysis.Analyzer}类的control flow analysis功能抽取出来.
 *
 * NOTE: 当前类抛弃了所有泛型相关的信息(V),抛弃了Frame、抛弃了Interpreter、抛弃了Value。
 *       但是,它仍然能够实现control flow analysis的功能。
 *
 * @see org.objectweb.asm.tree.analysis.Analyzer
 */
public class ControlFlowAnalyzer implements Opcodes {

    private InsnList insnList;
    private int insnListSize;
    private List<TryCatchBlockNode>[] handlers;

    /**
     * 记录需要处理的instructions.
     *
     * NOTE: 这三个字段为一组,应该一起处理,最好是放到同一个方法里来处理。
     * 因此,我就加了三个新方法。
     * {@link #initInstructionsToProcess()}、{@link #addInstructionsToProcess(int)}和
     * {@link #removeInstructionsToProcess()}
     *
     * @see #initInstructionsToProcess()
     * @see #addInstructionsToProcess(int)
     * @see #removeInstructionsToProcess()
     */
    private boolean[] inInstructionsToProcess;
    private int[] instructionsToProcess;
    private int numInstructionsToProcess;

    public ControlFlowAnalyzer() {
    }

    public List<TryCatchBlockNode> getHandlers(final int insnIndex) {
        return handlers[insnIndex];
    }


    @SuppressWarnings("unchecked")
    // NOTE: analyze方法的返回值类型变成了void类型。
    public void analyze(final String owner, final MethodNode method) throws AnalyzerException {
        if ((method.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
            return;
        }
        insnList = method.instructions;
        insnListSize = insnList.size();
        handlers = (List<TryCatchBlockNode>[]) new List<?>[insnListSize];

        initInstructionsToProcess();

        // For each exception handler, and each instruction within its range, record in 'handlers' the
        // fact that execution can flow from this instruction to the exception handler.
        for (int i = 0; i < method.tryCatchBlocks.size(); ++i) {
            TryCatchBlockNode tryCatchBlock = method.tryCatchBlocks.get(i);
            int startIndex = insnList.indexOf(tryCatchBlock.start);
            int endIndex = insnList.indexOf(tryCatchBlock.end);
            for (int j = startIndex; j < endIndex; ++j) {
                List<TryCatchBlockNode> insnHandlers = handlers[j];
                if (insnHandlers == null) {
                    insnHandlers = new ArrayList<>();
                    handlers[j] = insnHandlers;
                }
                insnHandlers.add(tryCatchBlock);
            }
        }


        // Initializes the data structures for the control flow analysis.
        // NOTE: 调用addInstructionsToProcess方法,传入参数0,启动整个循环过程。
        addInstructionsToProcess(0);
        init(owner, method);

        // Control flow analysis.
        while (numInstructionsToProcess > 0) {
            // Get and remove one instruction from the list of instructions to process.
            int insnIndex = removeInstructionsToProcess();

            // Simulate the execution of this instruction.
            AbstractInsnNode insnNode = method.instructions.get(insnIndex);
            int insnOpcode = insnNode.getOpcode();
            int insnType = insnNode.getType();

            if (insnType == AbstractInsnNode.LABEL
                    || insnType == AbstractInsnNode.LINE
                    || insnType == AbstractInsnNode.FRAME) {
                newControlFlowEdge(insnIndex, insnIndex + 1);
            }
            else {
                if (insnNode instanceof JumpInsnNode) {
                    JumpInsnNode jumpInsn = (JumpInsnNode) insnNode;
                    if (insnOpcode != GOTO && insnOpcode != JSR) {
                        newControlFlowEdge(insnIndex, insnIndex + 1);
                    }
                    int jumpInsnIndex = insnList.indexOf(jumpInsn.label);
                    newControlFlowEdge(insnIndex, jumpInsnIndex);
                }
                else if (insnNode instanceof LookupSwitchInsnNode) {
                    LookupSwitchInsnNode lookupSwitchInsn = (LookupSwitchInsnNode) insnNode;
                    int targetInsnIndex = insnList.indexOf(lookupSwitchInsn.dflt);
                    newControlFlowEdge(insnIndex, targetInsnIndex);
                    for (int i = 0; i < lookupSwitchInsn.labels.size(); ++i) {
                        LabelNode label = lookupSwitchInsn.labels.get(i);
                        targetInsnIndex = insnList.indexOf(label);
                        newControlFlowEdge(insnIndex, targetInsnIndex);
                    }
                }
                else if (insnNode instanceof TableSwitchInsnNode) {
                    TableSwitchInsnNode tableSwitchInsn = (TableSwitchInsnNode) insnNode;
                    int targetInsnIndex = insnList.indexOf(tableSwitchInsn.dflt);
                    newControlFlowEdge(insnIndex, targetInsnIndex);
                    for (int i = 0; i < tableSwitchInsn.labels.size(); ++i) {
                        LabelNode label = tableSwitchInsn.labels.get(i);
                        targetInsnIndex = insnList.indexOf(label);
                        newControlFlowEdge(insnIndex, targetInsnIndex);
                    }
                }
                else if (insnOpcode != ATHROW && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
                    newControlFlowEdge(insnIndex, insnIndex + 1);
                }
            }

            List<TryCatchBlockNode> insnHandlers = handlers[insnIndex];
            if (insnHandlers != null) {
                for (TryCatchBlockNode tryCatchBlock : insnHandlers) {
                    newControlFlowExceptionEdge(insnIndex, tryCatchBlock);
                }
            }

        }
    }


    protected void init(final String owner, final MethodNode method) throws AnalyzerException {
        // Nothing to do.
    }

    // NOTE: 这是一个新添加的方法
    private void initInstructionsToProcess() {
        inInstructionsToProcess = new boolean[insnListSize];
        instructionsToProcess = new int[insnListSize];
        numInstructionsToProcess = 0;
    }

    // NOTE: 这是一个新添加的方法
    private int removeInstructionsToProcess() {
        int insnIndex = this.instructionsToProcess[--numInstructionsToProcess];
        inInstructionsToProcess[insnIndex] = false;
        return insnIndex;
    }

    // NOTE: 这是一个新添加的方法
    private void addInstructionsToProcess(final int insnIndex) {
        if (!inInstructionsToProcess[insnIndex]) {
            inInstructionsToProcess[insnIndex] = true;
            instructionsToProcess[numInstructionsToProcess++] = insnIndex;
        }
    }

    protected void newControlFlowEdge(final int insnIndex, final int successorIndex) {
        // Nothing to do.
        addInstructionsToProcess(successorIndex);
    }

    protected void newControlFlowExceptionEdge(final int insnIndex, final TryCatchBlockNode tryCatchBlock) {
        newControlFlowExceptionEdge(insnIndex, insnList.indexOf(tryCatchBlock.handler));
    }

    protected void newControlFlowExceptionEdge(final int insnIndex, final int successorIndex) {
        // Nothing to do.
        addInstructionsToProcess(successorIndex);
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/ControlFlowAnalyzer2.java
================================================
package lsieun.asm.analysis;

import lsieun.asm.analysis.graph.InsnBlock;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.AnalyzerException;

import java.util.List;

public class ControlFlowAnalyzer2 extends ControlFlowAnalyzer{
    private AbstractInsnNode[] nodeArray;
    public InsnBlock[] blocks;

    public ControlFlowAnalyzer2() {

    }

    @Override
    public void analyze(String owner, MethodNode method) throws AnalyzerException {
        nodeArray = method.instructions.toArray();
        int length = nodeArray.length;
        blocks = new InsnBlock[length];
        InsnText insnText = new InsnText();
        for (int i = 0; i < length; i++) {
            blocks[i] = getBlock(i);
            AbstractInsnNode node = nodeArray[i];
            List<String> lines = insnText.toLines(node);
            blocks[i].addLines(lines);
        }

        super.analyze(owner, method);
    }

    @Override
    protected void newControlFlowEdge(int insnIndex, int successorIndex) {
        // 首先,处理自己的代码逻辑
        AbstractInsnNode insnNode = nodeArray[insnIndex];
        int insnOpcode = insnNode.getOpcode();
        int insnType = insnNode.getType();

        if (insnType == AbstractInsnNode.JUMP_INSN) {
            if ((insnIndex + 1) == successorIndex) {
                addNext(insnIndex, successorIndex);
            }
            else {
                addJump(insnIndex, successorIndex);
            }
        }
        else if (insnOpcode == LOOKUPSWITCH) {
            addJump(insnIndex, successorIndex);
        }
        else if (insnOpcode == TABLESWITCH) {
            addJump(insnIndex, successorIndex);
        }
        else if (insnOpcode == RET) {
            addJump(insnIndex, successorIndex);
        }
        else if (insnOpcode == ATHROW || (insnOpcode >= IRETURN && insnOpcode <= RETURN)) {
            assert false : "should not be here";
            removeNextAndJump(insnIndex);
        }
        else {
            addNext(insnIndex, successorIndex);
        }

        // 其次,调用父类的方法实现
        super.newControlFlowEdge(insnIndex, successorIndex);
    }

    private void addNext(int fromIndex, int toIndex) {
        InsnBlock currentBlock = getBlock(fromIndex);
        InsnBlock nextBlock = getBlock(toIndex);
        currentBlock.addNext(nextBlock);
    }

    private void addJump(int fromIndex, int toIndex) {
        InsnBlock currentBlock = getBlock(fromIndex);
        InsnBlock nextBlock = getBlock(toIndex);
        currentBlock.addJump(nextBlock);
    }

    private void removeNextAndJump(int insnIndex) {
        InsnBlock currentBlock = getBlock(insnIndex);
        currentBlock.nextBlockList.clear();
        currentBlock.jumpBlockList.clear();
    }

    private InsnBlock getBlock(int insnIndex) {
        InsnBlock block = blocks[insnIndex];
        if (block == null){
            block = new InsnBlock();
            blocks[insnIndex] = block;
        }
        return block;
    }

    public InsnBlock[] getBlocks() {
        return blocks;
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/ControlFlowEdgeAnalyzer.java
================================================
package lsieun.asm.analysis;

import lsieun.asm.analysis.graph.InsnBlock;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.*;

import java.util.List;

public class ControlFlowEdgeAnalyzer<V extends Value> extends Analyzer<V> {
    private AbstractInsnNode[] nodeArray;
    public InsnBlock[] blocks;

    public ControlFlowEdgeAnalyzer(Interpreter<V> interpreter) {
        super(interpreter);
    }

    @Override
    public Frame<V>[] analyze(String owner, MethodNode method) throws AnalyzerException {
        nodeArray = method.instructions.toArray();
        int length = nodeArray.length;
        blocks = new InsnBlock[length];
        InsnText insnText = new InsnText();
        for (int i = 0; i < length; i++) {
            blocks[i] = getBlock(i);
            AbstractInsnNode node = nodeArray[i];
            List<String> lines = insnText.toLines(node);
            blocks[i].addLines(lines);
        }

        return super.analyze(owner, method);
    }

    @Override
    protected void newControlFlowEdge(int insnIndex, int successorIndex) {
        // 首先,处理自己的代码逻辑
        AbstractInsnNode insnNode = nodeArray[insnIndex];
        int insnOpcode = insnNode.getOpcode();
        int insnType = insnNode.getType();

        if (insnType == AbstractInsnNode.JUMP_INSN) {
            if ((insnIndex + 1) == successorIndex) {
                addNext(insnIndex, successorIndex);
            }
            else {
                addJump(insnIndex, successorIndex);
            }
        }
        else if (insnOpcode == LOOKUPSWITCH) {
            addJump(insnIndex, successorIndex);
        }
        else if (insnOpcode == TABLESWITCH) {
            addJump(insnIndex, successorIndex);
        }
        else if (insnOpcode == RET) {
            addJump(insnIndex, successorIndex);
        }
        else if (insnOpcode == ATHROW || (insnOpcode >= IRETURN && insnOpcode <= RETURN)) {
            assert false : "should not be here";
            removeNextAndJump(insnIndex);
        }
        else {
            addNext(insnIndex, successorIndex);
        }

        // 其次,调用父类的方法实现
        super.newControlFlowEdge(insnIndex, successorIndex);
    }

    private void addNext(int fromIndex, int toIndex) {
        InsnBlock currentBlock = getBlock(fromIndex);
        InsnBlock nextBlock = getBlock(toIndex);
        currentBlock.addNext(nextBlock);
    }

    private void addJump(int fromIndex, int toIndex) {
        InsnBlock currentBlock = getBlock(fromIndex);
        InsnBlock nextBlock = getBlock(toIndex);
        currentBlock.addJump(nextBlock);
    }

    private void removeNextAndJump(int insnIndex) {
        InsnBlock currentBlock = getBlock(insnIndex);
        currentBlock.nextBlockList.clear();
        currentBlock.jumpBlockList.clear();
    }

    private InsnBlock getBlock(int insnIndex) {
        InsnBlock block = blocks[insnIndex];
        if (block == null){
            block = new InsnBlock();
            blocks[insnIndex] = block;
        }
        return block;
    }

    public InsnBlock[] getBlocks() {
        return blocks;
    }

}


================================================
FILE: src/main/java/lsieun/asm/analysis/ControlFlowEdgeAnalyzer2.java
================================================
package lsieun.asm.analysis;

import lsieun.asm.analysis.graph.InsnBlock;
import org.objectweb.asm.tree.analysis.Interpreter;
import org.objectweb.asm.tree.analysis.Value;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ControlFlowEdgeAnalyzer2<V extends Value> extends ControlFlowEdgeAnalyzer<V> {

    public ControlFlowEdgeAnalyzer2(Interpreter<V> interpreter) {
        super(interpreter);
    }

    @Override
    public InsnBlock[] getBlocks() {
        //(1)调用父类实现
        InsnBlock[] blocks = super.getBlocks();

        //(2)如果结果为空,则提前返回
        if (blocks == null || blocks.length < 1) {
            return blocks;
        }

        //(3)记录“分隔点”
        Set<InsnBlock> newBlockSet = new HashSet<>();
        int length = blocks.length;
        for (int i = 0; i < length; i++) {
            InsnBlock currentBlock = blocks[i];
            List<InsnBlock> nextBlockList = currentBlock.nextBlockList;
            List<InsnBlock> jumpBlockList = currentBlock.jumpBlockList;

            boolean hasNext = false;
            boolean hasJump = false;

            if (nextBlockList.size() > 0) {
                hasNext = true;
            }

            if (jumpBlockList.size() > 0) {
                hasJump = true;
            }

            if (!hasNext && (i + 1) < length) {
                newBlockSet.add(blocks[i + 1]);
            }

            if (hasJump) {
                newBlockSet.addAll(jumpBlockList);

                if (hasNext) {
                    newBlockSet.add(blocks[i + 1]);
                }
            }
        }

        //(4)利用“分隔点”,合并成不同的分组
        List<InsnBlock> resultList = new ArrayList<>();
        for (int i = 0; i < length; i++) {
            InsnBlock currentBlock = blocks[i];

            if (i == 0) {
                resultList.add(currentBlock);
            }
            else if (newBlockSet.contains(currentBlock)) {
                resultList.add(currentBlock);
            }
            else {
                int size = resultList.size();
                InsnBlock lastBlock = resultList.get(size - 1);
                lastBlock.lines.addAll(currentBlock.lines);
                lastBlock.jumpBlockList.clear();
                lastBlock.jumpBlockList.addAll(currentBlock.jumpBlockList);
                lastBlock.nextBlockList.clear();
                lastBlock.nextBlockList.addAll(currentBlock.nextBlockList);
            }
        }

        return resultList.toArray(new InsnBlock[0]);
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/ControlFlowGraphAnalyzer.java
================================================
package lsieun.asm.analysis;

import lsieun.asm.analysis.graph.InsnBlock;
import org.objectweb.asm.tree.*;

import java.util.*;

import static org.objectweb.asm.Opcodes.*;

public class ControlFlowGraphAnalyzer {
    private final Set<LabelNode> jumpLabelSet = new HashSet<>();
    private final Map<LabelNode, Set<InsnBlock>> jumpLabelMap = new HashMap<>();
    private final Map<LabelNode, InsnBlock> labelInBlockMap = new HashMap<>();
    private final InsnText insnText = new InsnText();

    private InsnBlock currentBlock;
    private final List<AbstractInsnNode> nodeList = new ArrayList<>();
    private final List<InsnBlock> blockList = new ArrayList<>();

    public ControlFlowGraphAnalyzer() {
        this.currentBlock = new InsnBlock();
    }

    public void analyze(MethodNode mn) {
        findJumpLabel(mn);
        instruction2Block(mn);
        linkBlocks();
    }


    private void findJumpLabel(MethodNode mn) {
        InsnList instructions = mn.instructions;

        for (AbstractInsnNode node : instructions) {
            if (node instanceof JumpInsnNode) {
                // 当前block与跳转目标的关系
                JumpInsnNode currentNode = (JumpInsnNode) node;
                jumpLabelSet.add(currentNode.label);
            }
            else if (node instanceof TableSwitchInsnNode) {
                // 当前block与跳转目标的关系
                TableSwitchInsnNode currentNode = (TableSwitchInsnNode) node;
                jumpLabelSet.add(currentNode.dflt);
                jumpLabelSet.addAll(currentNode.labels);
            }
            else if (node instanceof LookupSwitchInsnNode) {
                // 当前block与跳转目标的关系
                LookupSwitchInsnNode currentNode = (LookupSwitchInsnNode) node;
                jumpLabelSet.add(currentNode.dflt);
                jumpLabelSet.addAll(currentNode.labels);
            }
        }

        List<TryCatchBlockNode> tryCatchBlocks = mn.tryCatchBlocks;
        for (TryCatchBlockNode node : tryCatchBlocks) {
            jumpLabelSet.add(node.handler);
        }
    }

    private void instruction2Block(MethodNode mn) {
        InsnList instructions = mn.instructions;

        for (AbstractInsnNode node : instructions) {
            int opcode = node.getOpcode();

            if (node instanceof JumpInsnNode) {
                nodeList.add(node);

                // 当前block收集数据完成
                completeBlock();

                // 当前block与跳转目标的关系
                JumpInsnNode currentNode = (JumpInsnNode) node;
                addJumpFromBlockToLabel(currentNode.label);

                // 当前block与下一个block的关系
                InsnBlock nextBlock = new InsnBlock();
                if ((opcode >= IFEQ && opcode <= IF_ACMPNE) || (opcode >= IFNULL && opcode <= IFNONNULL)) {
                    currentBlock.nextBlockList.add(nextBlock);
                }

                // 下一个block成为当前block
                currentBlock = nextBlock;
            }
            else if (node instanceof TableSwitchInsnNode) {
                nodeList.add(node);

                // 当前block收集数据完成
                completeBlock();

                // 当前block与跳转目标的关系
                TableSwitchInsnNode currentNode = (TableSwitchInsnNode) node;
                int min = currentNode.min;
                int max = currentNode.max;
                for (int i = min; i <= max; i++) {
                    addJumpFromBlockToLabel(currentNode.labels.get(i - min));
                }
                addJumpFromBlockToLabel(currentNode.dflt);

                // 下一个block成为当前block
                InsnBlock nextBlock = new InsnBlock();
                currentBlock = nextBlock;
            }
            else if (node instanceof LookupSwitchInsnNode) {
                nodeList.add(node);

                // 当前block收集数据完成
                completeBlock();

                // 当前block与跳转目标的关系
                LookupSwitchInsnNode currentNode = (LookupSwitchInsnNode) node;
                List<LabelNode> labels = currentNode.labels;
                for (LabelNode labelNode : labels) {
                    addJumpFromBlockToLabel(labelNode);
                }
                addJumpFromBlockToLabel(currentNode.dflt);

                // 下一个block成为当前block
                InsnBlock nextBlock = new InsnBlock();
                currentBlock = nextBlock;
            }
            else if (node instanceof LabelNode) {
                LabelNode currentNode = (LabelNode) node;

                if (jumpLabelSet.contains(currentNode)) {
                    if (nodeList.size() > 0) {
                        // 当前block收集数据完成
                        completeBlock();

                        // 下一个block成为当前block
                        InsnBlock nextBlock = new InsnBlock();
                        currentBlock.nextBlockList.add(nextBlock);
                        currentBlock = nextBlock;
                    }

                }

                nodeList.add(node);
                labelInBlockMap.put(currentNode, currentBlock);
            }
            else if (node instanceof InsnNode) {
                nodeList.add(node);

                // 当前block收集数据完成
                if ((opcode >= IRETURN && opcode <= RETURN) || (opcode == ATHROW)) {
                    completeBlock();

                    InsnBlock nextBlock = new InsnBlock();
                    currentBlock = nextBlock;
                }

            }
            else {
                nodeList.add(node);
            }
        }

        if (nodeList.size() > 0) {
            // 当前block收集数据完成
            completeBlock();
        }
    }

    private void linkBlocks() {
        for (Map.Entry<LabelNode, Set<InsnBlock>> item : jumpLabelMap.entrySet()) {
            LabelNode key = item.getKey();
            Set<InsnBlock> set = item.getValue();

            InsnBlock targetBlock = labelInBlockMap.get(key);
            for (InsnBlock block : set) {
                block.jumpBlockList.add(targetBlock);
            }
        }
    }


    private void addJumpFromBlockToLabel(LabelNode labelNode) {
        Set<InsnBlock> list = jumpLabelMap.get(labelNode);
        if (list != null) {
            list.add(currentBlock);

        }
        else {
            list = new HashSet<>();
            list.add(currentBlock);
            jumpLabelMap.put(labelNode, list);
        }
    }

    private void completeBlock() {
        for (AbstractInsnNode node : nodeList) {
            List<String> lines = insnText.toLines(node);
            currentBlock.addLines(lines);
        }

        nodeList.clear();
        blockList.add(currentBlock);
    }

    public InsnBlock[] getBlocks() {
        return blockList.toArray(new InsnBlock[0]);
    }

}


================================================
FILE: src/main/java/lsieun/asm/analysis/DataFlowAnalyzer.java
================================================
package lsieun.asm.analysis;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.Frame;
import org.objectweb.asm.tree.analysis.Interpreter;
import org.objectweb.asm.tree.analysis.Value;

import java.util.ArrayList;
import java.util.List;

public class DataFlowAnalyzer<V extends Value> implements Opcodes {

    private final Interpreter<V> interpreter;

    // 数据输入:指令集和异常处理
    private InsnList insnList;
    private int insnListSize;
    private List<TryCatchBlockNode>[] handlers;

    // 中间状态:记录需要哪一个指令需要处理
    private boolean[] inInstructionsToProcess;
    private int[] instructionsToProcess;
    private int numInstructionsToProcess;

    // 数据输出:最终的返回结果
    private Frame<V>[] frames;

    public DataFlowAnalyzer(final Interpreter<V> interpreter) {
        this.interpreter = interpreter;
    }

    public List<TryCatchBlockNode> getHandlers(final int insnIndex) {
        return handlers[insnIndex];
    }

    public Frame<V>[] getFrames() {
        return frames;
    }


    @SuppressWarnings("unchecked")
    public Frame<V>[] analyze(final String owner, final MethodNode method) throws AnalyzerException {
        if ((method.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
            frames = (Frame<V>[]) new Frame<?>[0];
            return frames;
        }
        insnList = method.instructions;
        insnListSize = insnList.size();
        handlers = (List<TryCatchBlockNode>[]) new List<?>[insnListSize];
        frames = (Frame<V>[]) new Frame<?>[insnListSize];
        inInstructionsToProcess = new boolean[insnListSize];
        instructionsToProcess = new int[insnListSize];
        numInstructionsToProcess = 0;

        // For each exception handler, and each instruction within its range, record in 'handlers' the
        // fact that execution can flow from this instruction to the exception handler.
        for (int i = 0; i < method.tryCatchBlocks.size(); ++i) {
            TryCatchBlockNode tryCatchBlock = method.tryCatchBlocks.get(i);
            int startIndex = insnList.indexOf(tryCatchBlock.start);
            int endIndex = insnList.indexOf(tryCatchBlock.end);
            for (int j = startIndex; j < endIndex; ++j) {
                List<TryCatchBlockNode> insnHandlers = handlers[j];
                if (insnHandlers == null) {
                    insnHandlers = new ArrayList<>();
                    handlers[j] = insnHandlers;
                }
                insnHandlers.add(tryCatchBlock);
            }
        }

        // Initializes the data structures for the control flow analysis.
        Frame<V> currentFrame = computeInitialFrame(owner, method);
        merge(0, currentFrame);
        init(owner, method);

        // Control flow analysis.
        while (numInstructionsToProcess > 0) {
            // Get and remove one instruction from the list of instructions to process.
            int insnIndex = instructionsToProcess[--numInstructionsToProcess];
            Frame<V> oldFrame = frames[insnIndex];
            inInstructionsToProcess[insnIndex] = false;

            // Simulate the execution of this instruction.
            AbstractInsnNode insnNode = null;
            try {
                insnNode = method.instructions.get(insnIndex);
                int insnOpcode = insnNode.getOpcode();
                int insnType = insnNode.getType();

                if (insnType == AbstractInsnNode.LABEL
                        || insnType == AbstractInsnNode.LINE
                        || insnType == AbstractInsnNode.FRAME) {
                    merge(insnIndex + 1, oldFrame);
                    newControlFlowEdge(insnIndex, insnIndex + 1);
                }
                else {
                    currentFrame.init(oldFrame).execute(insnNode, interpreter);

                    if (insnNode instanceof JumpInsnNode) {
                        JumpInsnNode jumpInsn = (JumpInsnNode) insnNode;
                        if (insnOpcode != GOTO && insnOpcode != JSR) {
                            currentFrame.initJumpTarget(insnOpcode, /* target = */ null);
                            merge(insnIndex + 1, currentFrame);
                            newControlFlowEdge(insnIndex, insnIndex + 1);
                        }
                        int jumpInsnIndex = insnList.indexOf(jumpInsn.label);
                        currentFrame.initJumpTarget(insnOpcode, jumpInsn.label);
                        merge(jumpInsnIndex, currentFrame);
                        newControlFlowEdge(insnIndex, jumpInsnIndex);
                    }
                    else if (insnNode instanceof LookupSwitchInsnNode) {
                        LookupSwitchInsnNode lookupSwitchInsn = (LookupSwitchInsnNode) insnNode;
                        int targetInsnIndex = insnList.indexOf(lookupSwitchInsn.dflt);
                        currentFrame.initJumpTarget(insnOpcode, lookupSwitchInsn.dflt);
                        merge(targetInsnIndex, currentFrame);
                        newControlFlowEdge(insnIndex, targetInsnIndex);
                        for (int i = 0; i < lookupSwitchInsn.labels.size(); ++i) {
                            LabelNode label = lookupSwitchInsn.labels.get(i);
                            targetInsnIndex = insnList.indexOf(label);
                            currentFrame.initJumpTarget(insnOpcode, label);
                            merge(targetInsnIndex, currentFrame);
                            newControlFlowEdge(insnIndex, targetInsnIndex);
                        }
                    }
                    else if (insnNode instanceof TableSwitchInsnNode) {
                        TableSwitchInsnNode tableSwitchInsn = (TableSwitchInsnNode) insnNode;
                        int targetInsnIndex = insnList.indexOf(tableSwitchInsn.dflt);
                        currentFrame.initJumpTarget(insnOpcode, tableSwitchInsn.dflt);
                        merge(targetInsnIndex, currentFrame);
                        newControlFlowEdge(insnIndex, targetInsnIndex);
                        for (int i = 0; i < tableSwitchInsn.labels.size(); ++i) {
                            LabelNode label = tableSwitchInsn.labels.get(i);
                            currentFrame.initJumpTarget(insnOpcode, label);
                            targetInsnIndex = insnList.indexOf(label);
                            merge(targetInsnIndex, currentFrame);
                            newControlFlowEdge(insnIndex, targetInsnIndex);
                        }
                    }
                    else if (insnOpcode != ATHROW && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
                        merge(insnIndex + 1, currentFrame);
                        newControlFlowEdge(insnIndex, insnIndex + 1);
                    }
                }

                List<TryCatchBlockNode> insnHandlers = handlers[insnIndex];
                if (insnHandlers != null) {
                    for (TryCatchBlockNode tryCatchBlock : insnHandlers) {
                        Type catchType;
                        if (tryCatchBlock.type == null) {
                            catchType = Type.getObjectType("java/lang/Throwable");
                        }
                        else {
                            catchType = Type.getObjectType(tryCatchBlock.type);
                        }
                        if (newControlFlowExceptionEdge(insnIndex, tryCatchBlock)) {
                            Frame<V> handler = newFrame(oldFrame);
                            handler.clearStack();
                            handler.push(interpreter.newExceptionValue(tryCatchBlock, handler, catchType));
                            merge(insnList.indexOf(tryCatchBlock.handler), handler);
                        }
                    }
                }
            }
            catch (AnalyzerException e) {
                throw new AnalyzerException(e.node, "Error at instruction " + insnIndex + ": " + e.getMessage(), e);
            }
            catch (RuntimeException e) {
                // DontCheck(IllegalCatch): can't be fixed, for backward compatibility.
                throw new AnalyzerException(insnNode, "Error at instruction " + insnIndex + ": " + e.getMessage(), e);
            }
        }

        return frames;
    }

    private Frame<V> computeInitialFrame(final String owner, final MethodNode method) {
        Frame<V> frame = newFrame(method.maxLocals, method.maxStack);
        int currentLocal = 0;
        boolean isInstanceMethod = (method.access & ACC_STATIC) == 0;
        if (isInstanceMethod) {
            Type ownerType = Type.getObjectType(owner);
            frame.setLocal(currentLocal, interpreter.newParameterValue(isInstanceMethod, currentLocal, ownerType));
            currentLocal++;
        }
        Type[] argumentTypes = Type.getArgumentTypes(method.desc);
        for (Type argumentType : argumentTypes) {
            frame.setLocal(
                    currentLocal,
                    interpreter.newParameterValue(isInstanceMethod, currentLocal, argumentType));
            currentLocal++;
            if (argumentType.getSize() == 2) {
                frame.setLocal(currentLocal, interpreter.newEmptyValue(currentLocal));
                currentLocal++;
            }
        }
        while (currentLocal < method.maxLocals) {
            frame.setLocal(currentLocal, interpreter.newEmptyValue(currentLocal));
            currentLocal++;
        }
        frame.setReturn(interpreter.newReturnTypeValue(Type.getReturnType(method.desc)));
        return frame;
    }


    protected void init(final String owner, final MethodNode method) throws AnalyzerException {
        // Nothing to do.
    }

    protected Frame<V> newFrame(final int numLocals, final int numStack) {
        return new Frame<>(numLocals, numStack);
    }

    protected Frame<V> newFrame(final Frame<? extends V> frame) {
        return new Frame<>(frame);
    }

    protected void newControlFlowEdge(final int insnIndex, final int successorIndex) {
        // Nothing to do.
    }

    protected boolean newControlFlowExceptionEdge(final int insnIndex, final TryCatchBlockNode tryCatchBlock) {
        return newControlFlowExceptionEdge(insnIndex, insnList.indexOf(tryCatchBlock.handler));
    }

    protected boolean newControlFlowExceptionEdge(final int insnIndex, final int successorIndex) {
        return true;
    }

    // -----------------------------------------------------------------------------------------------

    private void merge(final int insnIndex, final Frame<V> frame)
            throws AnalyzerException {
        boolean changed;
        Frame<V> oldFrame = frames[insnIndex];
        if (oldFrame == null) {
            frames[insnIndex] = newFrame(frame);
            changed = true;
        }
        else {
            changed = oldFrame.merge(frame, interpreter);
        }

        if (changed && !inInstructionsToProcess[insnIndex]) {
            inInstructionsToProcess[insnIndex] = true;
            instructionsToProcess[numInstructionsToProcess++] = insnIndex;
        }
    }

}


================================================
FILE: src/main/java/lsieun/asm/analysis/InsnText.java
================================================
package lsieun.asm.analysis;

import lsieun.utils.OpcodeConst;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.objectweb.asm.Opcodes.BIPUSH;
import static org.objectweb.asm.Opcodes.SIPUSH;

public class InsnText {
    private static final String INSTRUCTION_FORMAT = "%s %s";

    private final Map<LabelNode, String> labelNames = new HashMap<>();

    public List<String> toLines(AbstractInsnNode[] array) {
        List<String> resultList = new ArrayList<>();
        if (array == null || array.length < 1) {
            return resultList;
        }

        for (AbstractInsnNode node : array) {
            List<String> lines = toLines(node);
            resultList.addAll(lines);
        }
        return resultList;
    }

    public List<String> toLines(AbstractInsnNode node) {
        List<String> resultList = new ArrayList<>();
        if (node instanceof TableSwitchInsnNode) {
            TableSwitchInsnNode currentNode = (TableSwitchInsnNode) node;
            List<String> list = table_switch_node_to_str_list(currentNode);
            resultList.addAll(list);
        }
        else if (node instanceof LookupSwitchInsnNode) {
            LookupSwitchInsnNode currentNode = (LookupSwitchInsnNode) node;
            List<String> list = lookup_switch_node_to_str_list(currentNode);
            resultList.addAll(list);
        }
        else {
            String item = node_to_str(node);
            resultList.add(item);
        }

        return resultList;
    }

    public String node_to_str(AbstractInsnNode currentNode) {
        if (currentNode instanceof InsnNode) {
            return getOpcodeName(currentNode);
        }
        else if (currentNode instanceof IntInsnNode) {
            int opcode = currentNode.getOpcode();
            String opcodeName = getOpcodeName(currentNode);
            IntInsnNode node = (IntInsnNode) currentNode;
            int operand = node.operand;
            if (opcode == BIPUSH || opcode == SIPUSH) {
                return String.format(INSTRUCTION_FORMAT, opcodeName, operand);
            }
            else {
                final String firstArg;
                switch (operand) {
                    case 4: {
                        firstArg = "4 (boolean)";
                        break;
                    }
                    case 5: {
                        firstArg = "5 (char)";
                        break;
                    }
                    case 6: {
                        firstArg = "6 (float)";
                        break;
                    }
                    case 7: {
                        firstArg = "7 (double)";
                        break;
                    }
                    case 8: {
                        firstArg = "8 (byte)";
                        break;
                    }
                    case 9: {
                        firstArg = "9 (short)";
                        break;
                    }
                    case 10: {
                        firstArg = "10 (int)";
                        break;
                    }
                    case 11: {
                        firstArg = "11 (long)";
                        break;
                    }
                    default:
                        throw new RuntimeException("atype is not supported: " + operand);
                }
                return String.format(INSTRUCTION_FORMAT, opcodeName, firstArg);
            }
        }
        else if (currentNode instanceof VarInsnNode) {
            String opcodeName = getOpcodeName(currentNode);
            VarInsnNode node = (VarInsnNode) currentNode;
            int var = node.var;
            if (var >= 0 && var <= 3) {
                return String.format("%s_%d", opcodeName, var);
            }
            else {
                return String.format(INSTRUCTION_FORMAT, opcodeName, var);
            }
        }
        else if (currentNode instanceof TypeInsnNode) {
            String opcodeName = getOpcodeName(currentNode);
            TypeInsnNode node = (TypeInsnNode) currentNode;
            String type = getSimpleName(node.desc);
            return String.format(INSTRUCTION_FORMAT, opcodeName, type);
        }
        else if (currentNode instanceof FieldInsnNode) {
            String opcodeName = getOpcodeName(currentNode);
            FieldInsnNode node = (FieldInsnNode) currentNode;
            String type = getSimpleName(node.owner);
            return String.format("%s %s.%s", opcodeName, type, node.name);
        }
        else if (currentNode instanceof MethodInsnNode) {
            String opcodeName = getOpcodeName(currentNode);
            MethodInsnNode node = (MethodInsnNode) currentNode;
            String type = getSimpleName(node.owner);
            return String.format("%s %s.%s", opcodeName, type, node.name);
        }
        else if (currentNode instanceof InvokeDynamicInsnNode) {
            String opcodeName = getOpcodeName(currentNode);
            InvokeDynamicInsnNode node = (InvokeDynamicInsnNode) currentNode;
            Type methodType = Type.getMethodType(node.desc);
            Type returnType = methodType.getReturnType();
            String type = getSimpleName(returnType.getInternalName());
            return String.format("%s %s.%s", opcodeName, type, node.name);
        }
        else if (currentNode instanceof JumpInsnNode) {
            String opcodeName = getOpcodeName(currentNode);
            JumpInsnNode node = (JumpInsnNode) currentNode;
            String labelName = getLabelName(node.label);
            return String.format(INSTRUCTION_FORMAT, opcodeName, labelName);
        }
        else if (currentNode instanceof LabelNode) {
            LabelNode node = (LabelNode) currentNode;
            return getLabelName(node);
        }
        else if (currentNode instanceof LdcInsnNode) {
            String opcodeName = getOpcodeName(currentNode);
            LdcInsnNode node = (LdcInsnNode) currentNode;
            Object cst = node.cst;
            if (cst instanceof Integer) {
                return String.format("%s %s(int)", opcodeName, cst);
            }
            else if (cst instanceof Float) {
                return String.format("%s %s(float)", opcodeName, cst);
            }
            else if (cst instanceof Long) {
                return String.format("%s %s(long)", opcodeName, cst);
            }
            else if (cst instanceof Double) {
                return String.format("%s %s(double)", opcodeName, cst);
            }
            else if (cst instanceof String) {
                return String.format("%s \"%s\"", opcodeName, cst);
            }
            else if (cst instanceof Class<?>) {
                return String.format("%s %s(class)", opcodeName, cst);
            }
            else {
                return String.format("%s %s", opcodeName, cst);
            }
        }
        else if (currentNode instanceof IincInsnNode) {
            String opcodeName = getOpcodeName(currentNode);
            IincInsnNode node = (IincInsnNode) currentNode;
            return String.format("%s %d %d", opcodeName, node.var, node.incr);
        }
        else if (currentNode instanceof MultiANewArrayInsnNode) {
            String opcodeName = getOpcodeName(currentNode);
            MultiANewArrayInsnNode node = (MultiANewArrayInsnNode) currentNode;
            String type = getSimpleName(node.desc);
            return String.format(INSTRUCTION_FORMAT, opcodeName, type);
        }
        else if (currentNode instanceof FrameNode) {
            return "FrameNode";
        }
        else if (currentNode instanceof LineNumberNode) {
            return "LineNumberNode";
        }
        else {
            System.out.println(currentNode.getClass());
        }
        return currentNode.toString();
    }

    public List<String> table_switch_node_to_str_list(TableSwitchInsnNode currentNode) {
        String opcodeName = getOpcodeName(currentNode);
        int min = currentNode.min;
        int max = currentNode.max;

        List<String> list = new ArrayList<>();
        list.add(String.format("%s {", opcodeName));
        for (int i = min; i <= max; i++) {
            LabelNode labelNode = currentNode.labels.get(i - min);
            String labelName = getLabelName(labelNode);
            list.add(String.format("    %d: %s", i, labelName));
        }
        list.add(String.format("    default: %s", getLabelName(currentNode.dflt)));
        list.add("}");
        return list;
    }

    public List<String> lookup_switch_node_to_str_list(LookupSwitchInsnNode currentNode) {
        String opcodeName = getOpcodeName(currentNode);
        List<Integer> keys = currentNode.keys;
        int size = keys.size();

        List<String> list = new ArrayList<>();
        list.add(String.format("%s {", opcodeName));
        for (int i = 0; i < size; i++) {
            int caseValue = keys.get(i);
            LabelNode labelNode = currentNode.labels.get(i);
            String labelName = getLabelName(labelNode);
            list.add(String.format("    %d: %s", caseValue, labelName));
        }
        list.add(String.format("    default: %s", getLabelName(currentNode.dflt)));
        list.add("}");
        return list;
    }

    private String getLabelName(LabelNode labelNode) {
        String labelName = labelNames.get(labelNode);
        if (labelName == null) {
            labelName = "L" + labelNames.size();
            labelNames.put(labelNode, labelName);
        }
        return labelName;
    }

    private static String getOpcodeName(AbstractInsnNode currentNode) {
        int opcode = currentNode.getOpcode();
        return OpcodeConst.getOpcodeName(opcode);
    }

    private static String getSimpleName(String descriptor) {
        int squareIndex = descriptor.lastIndexOf("[");
        String prefix = descriptor.substring(0, squareIndex + 1);

        String simpleName = descriptor.substring(squareIndex + 1);
        if (simpleName.startsWith("L") && simpleName.endsWith(";")) {
            simpleName = simpleName.substring(1, simpleName.length() - 1);
        }

        int slashIndex = simpleName.lastIndexOf("/");
        simpleName = simpleName.substring(slashIndex + 1);

        return prefix + simpleName;
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/MockAnalyzer.java
================================================
package lsieun.asm.analysis;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.Frame;
import org.objectweb.asm.tree.analysis.Interpreter;
import org.objectweb.asm.tree.analysis.Value;

public class MockAnalyzer<V extends Value> implements Opcodes {
    private final Interpreter<V> interpreter;

    public MockAnalyzer(Interpreter<V> interpreter) {
        this.interpreter = interpreter;
    }

    @SuppressWarnings("unchecked")
    public Frame<V>[] analyze(String owner, MethodNode method) throws AnalyzerException {
        // 第一步,如果是abstract或native方法,则直接返回。
        if ((method.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
            return (Frame<V>[]) new Frame<?>[0];
        }

        // 第二步,定义局部变量
        // (1)数据输入:获取指令集
        InsnList insnList = method.instructions;
        int size = insnList.size();

        // (2)中间状态:记录需要哪一个指令需要处理
        boolean[] instructionsToProcess = new boolean[size];

        // (3)数据输出:最终的返回结果
        Frame<V>[] frames = (Frame<V>[]) new Frame<?>[size];

        // 第三步,开始计算
        // (1)开始计算:根据方法的参数,计算方法的初始Frame
        Frame<V> currentFrame = computeInitialFrame(owner, method);
        merge(frames, 0, currentFrame, instructionsToProcess);

        // (2)开始计算:根据方法的每一条指令,计算相应的Frame
        while (getCount(instructionsToProcess) > 0) {
            // 获取需要处理的指令索引(insnIndex)和旧的Frame(oldFrame)
            int insnIndex = getFirst(instructionsToProcess);
            Frame<V> oldFrame = frames[insnIndex];
            instructionsToProcess[insnIndex] = false;

            // 模拟每一条指令的执行
            try {
                AbstractInsnNode insnNode = method.instructions.get(insnIndex);
                int insnOpcode = insnNode.getOpcode();
                int insnType = insnNode.getType();

                // 这三者并不是真正的指令,分别表示Label、LineNumberTable和Frame
                if (insnType == AbstractInsnNode.LABEL
                        || insnType == AbstractInsnNode.LINE
                        || insnType == AbstractInsnNode.FRAME) {
                    merge(frames, insnIndex + 1, oldFrame, instructionsToProcess);
                }
                else {
                    // 这里是真正的指令
                    currentFrame.init(oldFrame).execute(insnNode, interpreter);

                    if (insnNode instanceof JumpInsnNode) {
                        JumpInsnNode jumpInsn = (JumpInsnNode) insnNode;
                        // if之后的语句
                        if (insnOpcode != GOTO) {
                            merge(frames, insnIndex + 1, currentFrame, instructionsToProcess);
                        }

                        // if和goto跳转之后的位置
                        int jumpInsnIndex = insnList.indexOf(jumpInsn.label);
                        merge(frames, jumpInsnIndex, currentFrame, instructionsToProcess);
                    }
                    else if (insnNode instanceof LookupSwitchInsnNode) {
                        LookupSwitchInsnNode lookupSwitchInsn = (LookupSwitchInsnNode) insnNode;

                        // lookupswitch的default情况
                        int targetInsnIndex = insnList.indexOf(lookupSwitchInsn.dflt);
                        merge(frames, targetInsnIndex, currentFrame, instructionsToProcess);

                        // lookupswitch的各种case情况
                        for (int i = 0; i < lookupSwitchInsn.labels.size(); ++i) {
                            LabelNode label = lookupSwitchInsn.labels.get(i);
                            targetInsnIndex = insnList.indexOf(label);
                            merge(frames, targetInsnIndex, currentFrame, instructionsToProcess);
                        }
                    }
                    else if (insnNode instanceof TableSwitchInsnNode) {
                        TableSwitchInsnNode tableSwitchInsn = (TableSwitchInsnNode) insnNode;

                        // tableswitch的default情况
                        int targetInsnIndex = insnList.indexOf(tableSwitchInsn.dflt);
                        merge(frames, targetInsnIndex, currentFrame, instructionsToProcess);

                        // tableswitch的各种case情况
                        for (int i = 0; i < tableSwitchInsn.labels.size(); ++i) {
                            LabelNode label = tableSwitchInsn.labels.get(i);
                            targetInsnIndex = insnList.indexOf(label);
                            merge(frames, targetInsnIndex, currentFrame, instructionsToProcess);
                        }
                    }
                    else if (insnOpcode != ATHROW && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
                        merge(frames, insnIndex + 1, currentFrame, instructionsToProcess);
                    }
                }
            }
            catch (AnalyzerException e) {
                throw new AnalyzerException(e.node, "Error at instruction " + insnIndex + ": " + e.getMessage(), e);
            }
        }

        return frames;
    }

    private int getCount(boolean[] array) {
        int count = 0;
        for (boolean flag : array) {
            if (flag) {
                count++;
            }
        }
        return count;
    }

    private int getFirst(boolean[] array) {
        int length = array.length;
        for (int i = 0; i < length; i++) {
            boolean flag = array[i];
            if (flag) {
                return i;
            }
        }
        return -1;
    }

    private Frame<V> computeInitialFrame(final String owner, final MethodNode method) {
        Frame<V> frame = new Frame<>(method.maxLocals, method.maxStack);
        int currentLocal = 0;

        // 第一步,判断是否需要存储this变量
        boolean isInstanceMethod = (method.access & ACC_STATIC) == 0;
        if (isInstanceMethod) {
            Type ownerType = Type.getObjectType(owner);
            V value = interpreter.newParameterValue(isInstanceMethod, currentLocal, ownerType);
            frame.setLocal(currentLocal, value);
            currentLocal++;
        }

        // 第二步,将方法的参数存入到local variable内
        Type[] argumentTypes = Type.getArgumentTypes(method.desc);
        for (Type argumentType : argumentTypes) {
            V value = interpreter.newParameterValue(isInstanceMethod, currentLocal, argumentType);
            frame.setLocal(currentLocal, value);
            currentLocal++;
            if (argumentType.getSize() == 2) {
                frame.setLocal(currentLocal, interpreter.newEmptyValue(currentLocal));
                currentLocal++;
            }
        }

        // 第三步,将local variable的剩余位置填补上空值
        while (currentLocal < method.maxLocals) {
            frame.setLocal(currentLocal, interpreter.newEmptyValue(currentLocal));
            currentLocal++;
        }

        // 第四步,设置返回值类型
        frame.setReturn(interpreter.newReturnTypeValue(Type.getReturnType(method.desc)));
        return frame;
    }

    /**
     * Merge old frame with new frame.
     *
     * @param frames 所有的frame信息。
     * @param insnIndex 当前指令的索引。
     * @param newFrame 新的frame
     * @param instructionsToProcess 记录哪一条指令需要处理
     * @throws AnalyzerException 分析错误,抛出此异常
     */
    private void merge(Frame<V>[] frames, int insnIndex, Frame<V> newFrame, boolean[] instructionsToProcess) throws AnalyzerException {
        boolean changed;
        Frame<V> oldFrame = frames[insnIndex];
        if (oldFrame == null) {
            frames[insnIndex] = new Frame<>(newFrame);
            changed = true;
        }
        else {
            changed = oldFrame.merge(newFrame, interpreter);
        }

        if (changed && !instructionsToProcess[insnIndex]) {
            instructionsToProcess[insnIndex] = true;
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/RemoveDeadCodeNode.java
================================================
package lsieun.asm.analysis;

import lsieun.asm.tree.transformer.MethodTransformer;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.*;

public class RemoveDeadCodeNode extends ClassNode {
    public RemoveDeadCodeNode(int api, ClassVisitor cv) {
        super(api);
        this.cv = cv;
    }

    @Override
    public void visitEnd() {
        // 首先,处理自己的代码逻辑
        MethodTransformer mt = new MethodRemoveDeadCodeTransformer(name, null);
        for (MethodNode mn : methods) {
            mt.transform(mn);
        }

        // 其次,调用父类的方法实现
        super.visitEnd();

        // 最后,向后续ClassVisitor传递
        if (cv != null) {
            accept(cv);
        }
    }

    private static class MethodRemoveDeadCodeTransformer extends MethodTransformer {
        private final String owner;

        public MethodRemoveDeadCodeTransformer(String owner, MethodTransformer mt) {
            super(mt);
            this.owner = owner;
        }

        @Override
        public void transform(MethodNode mn) {
            // 首先,处理自己的代码逻辑
            Analyzer<BasicValue> analyzer = new Analyzer<>(new BasicInterpreter());
            try {
                analyzer.analyze(owner, mn);
                Frame<BasicValue>[] frames = analyzer.getFrames();
                AbstractInsnNode[] insnNodes = mn.instructions.toArray();
                for (int i = 0; i < frames.length; i++) {
                    if (frames[i] == null && !(insnNodes[i] instanceof LabelNode)) {
                        mn.instructions.remove(insnNodes[i]);
                    }
                }
            }
            catch (AnalyzerException ex) {
                ex.printStackTrace();
            }

            // 其次,调用父类的方法实现
            super.transform(mn);
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/RemoveDeadCodeVisitor.java
================================================
package lsieun.asm.analysis;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.*;

public class RemoveDeadCodeVisitor extends ClassVisitor {
    private String owner;

    public RemoveDeadCodeVisitor(int api, ClassVisitor cv) {
        super(api, cv);
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        super.visit(version, access, name, signature, superName, interfaces);
        this.owner = name;
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        if (mv != null) {
            mv = new MethodRemoveDeadCodeAdapter(api, owner, access, name, descriptor, mv);
        }
        return mv;
    }

    private static class MethodRemoveDeadCodeAdapter extends MethodVisitor {
        private final String owner;
        private final MethodVisitor next;

        public MethodRemoveDeadCodeAdapter(int api, String owner, int access, String name, String desc, MethodVisitor next) {
            super(api, new MethodNode(access, name, desc, null, null));
            this.owner = owner;
            this.next = next;
        }

        @Override
        public void visitEnd() {
            // 首先,处理自己的代码逻辑
            MethodNode mn = (MethodNode) mv;
            Analyzer<BasicValue> analyzer = new Analyzer<>(new BasicInterpreter());
            try {
                analyzer.analyze(owner, mn);
                Frame<BasicValue>[] frames = analyzer.getFrames();
                AbstractInsnNode[] insnNodes = mn.instructions.toArray();
                for (int i = 0; i < frames.length; i++) {
                    if (frames[i] == null && !(insnNodes[i] instanceof LabelNode)) {
                        mn.instructions.remove(insnNodes[i]);
                    }
                }
            }
            catch (AnalyzerException ex) {
                ex.printStackTrace();
            }

            // 其次,调用父类的方法实现
            super.visitEnd();

            // 最后,向后续MethodVisitor传递
            if (next != null) {
                mn.accept(next);
            }
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/RemoveUnusedCastNode.java
================================================
package lsieun.asm.analysis;

import lsieun.asm.tree.transformer.MethodTransformer;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.analysis.*;

import static org.objectweb.asm.Opcodes.CHECKCAST;

public class RemoveUnusedCastNode extends ClassNode {
    public RemoveUnusedCastNode(int api, ClassVisitor cv) {
        super(api);
        this.cv = cv;
    }

    @Override
    public void visitEnd() {
        // 首先,处理自己的代码逻辑
        MethodTransformer mt = new MethodRemoveUnusedCastTransformer(name, null);
        for (MethodNode mn : methods) {
            if ("<init>".equals(mn.name) || "<clinit>".equals(mn.name)) {
                continue;
            }
            InsnList insns = mn.instructions;
            if (insns.size() == 0) {
                continue;
            }
            mt.transform(mn);
        }

        // 其次,调用父类的方法实现
        super.visitEnd();

        // 最后,向后续ClassVisitor传递
        if (cv != null) {
            accept(cv);
        }
    }

    private static class MethodRemoveUnusedCastTransformer extends MethodTransformer {
        private final String owner;

        public MethodRemoveUnusedCastTransformer(String owner, MethodTransformer mt) {
            super(mt);
            this.owner = owner;
        }

        @Override
        public void transform(MethodNode mn) {
            // 首先,处理自己的代码逻辑
            Analyzer<BasicValue> analyzer = new Analyzer<>(new SimpleVerifier());
            try {
                Frame<BasicValue>[] frames = analyzer.analyze(owner, mn);
                AbstractInsnNode[] insnNodes = mn.instructions.toArray();
                for (int i = 0; i < insnNodes.length; i++) {
                    AbstractInsnNode insn = insnNodes[i];
                    if (insn.getOpcode() == CHECKCAST) {
                        Frame<BasicValue> f = frames[i];
                        if (f != null && f.getStackSize() > 0) {
                            BasicValue operand = f.getStack(f.getStackSize() - 1);
                            Class<?> to = getClass(((TypeInsnNode) insn).desc);
                            Class<?> from = getClass(operand.getType());
                            if (to.isAssignableFrom(from)) {
                                mn.instructions.remove(insn);
                            }
                        }
                    }
                }
            }
            catch (AnalyzerException ex) {
                ex.printStackTrace();
            }

            // 其次,调用父类的方法实现
            super.transform(mn);
        }

        private static Class<?> getClass(String desc) {
            try {
                return Class.forName(desc.replace('/', '.'));
            }
            catch (ClassNotFoundException ex) {
                throw new RuntimeException(ex.toString());
            }
        }

        private static Class<?> getClass(Type t) {
            if (t.getSort() == Type.OBJECT) {
                return getClass(t.getInternalName());
            }
            return getClass(t.getDescriptor());
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/RemoveUnusedCastVisitor.java
================================================
package lsieun.asm.analysis;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.commons.AnalyzerAdapter;

import static org.objectweb.asm.Opcodes.*;

public class RemoveUnusedCastVisitor extends ClassVisitor {
    private String owner;

    public RemoveUnusedCastVisitor(int api, ClassVisitor classVisitor) {
        super(api, classVisitor);
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        super.visit(version, access, name, signature, superName, interfaces);
        this.owner = name;
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        if (mv != null && !name.equals("<init>")) {
            boolean isAbstractMethod = (access & ACC_ABSTRACT) != 0;
            boolean isNativeMethod = (access & ACC_NATIVE) != 0;
            if (!isAbstractMethod && !isNativeMethod) {
                RemoveUnusedCastAdapter adapter = new RemoveUnusedCastAdapter(api, mv);
                adapter.aa = new AnalyzerAdapter(owner, access, name, descriptor, adapter);
                return adapter.aa;
            }
        }

        return mv;
    }

    private static class RemoveUnusedCastAdapter extends MethodVisitor {
        public AnalyzerAdapter aa;

        public RemoveUnusedCastAdapter(int api, MethodVisitor methodVisitor) {
            super(api, methodVisitor);
        }

        @Override
        public void visitTypeInsn(int opcode, String type) {
            // 首先,处理自己的代码逻辑
            if (opcode == CHECKCAST) {
                Class<?> to = getClass(type);
                if (aa.stack != null && aa.stack.size() > 0) {
                    Object operand = aa.stack.get(aa.stack.size() - 1);
                    if (operand instanceof String) {
                        Class<?> from = getClass((String) operand);
                        if (to.isAssignableFrom(from)) {
                            return;
                        }
                    }
                }
            }

            // 其次,调用父类的方法实现
            super.visitTypeInsn(opcode, type);
        }

        private static Class<?> getClass(String desc) {
            try {
                return Class.forName(desc.replace('/', '.'));
            }
            catch (ClassNotFoundException ex) {
                throw new RuntimeException(ex.toString());
            }
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/cc/CyclomaticComplexity.java
================================================
package lsieun.asm.analysis.cc;

import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.*;

public class CyclomaticComplexity {
    public static int getCyclomaticComplexity(String owner, MethodNode mn) throws AnalyzerException {
        // 第一步,获取Frame信息
        Analyzer<BasicValue> analyzer = new CyclomaticComplexityAnalyzer<>(new BasicInterpreter());
        Frame<BasicValue>[] frames = analyzer.analyze(owner, mn);

        // 第二步,计算复杂度
        int edges = 0;
        int nodes = 0;
        for (Frame<BasicValue> frame : frames) {
            if (frame != null) {
                edges += ((CyclomaticComplexityFrame<BasicValue>) frame).successors.size();
                nodes += 1;
            }
        }
        return edges - nodes + 2;
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/cc/CyclomaticComplexityAnalyzer.java
================================================
package lsieun.asm.analysis.cc;

import org.objectweb.asm.tree.analysis.*;

public class CyclomaticComplexityAnalyzer<V extends Value> extends Analyzer<V> {
    public CyclomaticComplexityAnalyzer(Interpreter<V> interpreter) {
        super(interpreter);
    }

    @Override
    protected Frame<V> newFrame(int numLocals, int numStack) {
        return new CyclomaticComplexityFrame<>(numLocals, numStack);
    }

    @Override
    protected Frame<V> newFrame(Frame<? extends V> frame) {
        return new CyclomaticComplexityFrame<>(frame);
    }

    @Override
    protected void newControlFlowEdge(int insnIndex, int successorIndex) {
        CyclomaticComplexityFrame<V> frame = (CyclomaticComplexityFrame<V>) getFrames()[insnIndex];
        frame.successors.add((CyclomaticComplexityFrame<V>) getFrames()[successorIndex]);
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/cc/CyclomaticComplexityFrame.java
================================================
package lsieun.asm.analysis.cc;

import org.objectweb.asm.tree.analysis.Frame;
import org.objectweb.asm.tree.analysis.Value;

import java.util.HashSet;
import java.util.Set;

public class CyclomaticComplexityFrame<V extends Value> extends Frame<V> {
    public Set<CyclomaticComplexityFrame<V>> successors = new HashSet<>();

    public CyclomaticComplexityFrame(int numLocals, int numStack) {
        super(numLocals, numStack);
    }

    public CyclomaticComplexityFrame(Frame<? extends V> frame) {
        super(frame);
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/cfg/ControlFlowBuilder.java
================================================
package lsieun.asm.analysis.cfg;

import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.AnalyzerException;

import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
import static org.objectweb.asm.Opcodes.ACC_NATIVE;

public final class ControlFlowBuilder {
    public static ControlFlowGraph buildCFG(String className, MethodNode methodNode) throws AnalyzerException {
        if ((methodNode.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
            throw new RuntimeException("method body is empty");
        }

        int size = methodNode.instructions.size();
        SimpleEdgeCreator edgeCreator = new SimpleEdgeCreator(size);
        FramelessAnalyzer myAnalyzer = new FramelessAnalyzer(edgeCreator);
        myAnalyzer.analyze(methodNode);


        int[][] transitions = new int[edgeCreator.transitions.length][];
        for (int i = 0; i < transitions.length; i++) {
            transitions[i] = edgeCreator.transitions[i].toNativeArray();
        }
        int[][] errorTransitions = new int[edgeCreator.errorTransitions.length][];
        for (int i = 0; i < errorTransitions.length; i++) {
            errorTransitions[i] = edgeCreator.errorTransitions[i].toNativeArray();
        }

        return new ControlFlowGraph(transitions, errorTransitions);
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/cfg/ControlFlowGraph.java
================================================
package lsieun.asm.analysis.cfg;

import java.util.Arrays;
import java.util.Formatter;

public final class ControlFlowGraph {
    public final int[][] transitions;
    public final int[][] errorTransitions;

    public ControlFlowGraph(int[][] transitions, int[][] errorTransitions) {
        this.transitions = transitions;
        this.errorTransitions = errorTransitions;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        Formatter fm = new Formatter(sb);
        fm.format("ControlFlowGraph%n");

        fm.format("Normal Transitions%n");
        int normalLength = transitions.length;
        for (int i = 0; i < normalLength; i++) {
            int[] array = transitions[i];
            fm.format("%03d    %s%n", i, Arrays.toString(array));
        }

        fm.format("Error Transitions%n");
        int errorLength = transitions.length;
        for (int i = 0; i < errorLength; i++) {
            int[] array = errorTransitions[i];
            fm.format("%03d    %s%n", i, Arrays.toString(array));
        }
        return sb.toString();
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/cfg/Edge.java
================================================
package lsieun.asm.analysis.cfg;

public final class Edge {
    public final int from;
    public final int to;

    public Edge(int from, int to) {
        this.from = from;
        this.to = to;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof Edge)) {
            return false;
        }
        Edge edge = (Edge) obj;
        return (from == edge.from) && (to == edge.to);
    }

    @Override
    public int hashCode() {
        return 31 * from + to;
    }
}

================================================
FILE: src/main/java/lsieun/asm/analysis/cfg/EdgeCreator.java
================================================
package lsieun.asm.analysis.cfg;

public interface EdgeCreator {
    void newControlFlowEdge(int insn, int successor);

    void newControlFlowExceptionEdge(int insn, int successor, boolean npe);
}

================================================
FILE: src/main/java/lsieun/asm/analysis/cfg/FramelessAnalyzer.java
================================================
package lsieun.asm.analysis.cfg;

import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.analysis.AnalyzerException;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static org.objectweb.asm.Opcodes.*;

/**
 * Specialized version of {@link org.objectweb.asm.tree.analysis.Analyzer}.
 * Calculation of fix-point of frames is removed, since frames are not needed to build control flow graph.
 * So, the main point here is handling of try-catch-finally blocks.
 */
public class FramelessAnalyzer {
    private static final Set<String> NPE_HANDLERS = new HashSet<>();

    static {
        NPE_HANDLERS.add("java/lang/Throwable");
        NPE_HANDLERS.add("java/lang/Exception");
        NPE_HANDLERS.add("java/lang/RuntimeException");
        NPE_HANDLERS.add("java/lang/NullPointerException");
    }

    protected boolean[] wasQueued;
    protected boolean[] queued;
    protected int[] queue;
    protected int top;
    protected final EdgeCreator myEdgeCreator;

    public FramelessAnalyzer(EdgeCreator creator) {
        myEdgeCreator = creator;
    }

    public void analyze(MethodNode m) throws AnalyzerException {
        int n = m.instructions.size();
        if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0 || n == 0) {
            return;
        }
        InsnList insns = m.instructions;
        List<TryCatchBlockNode>[] handlers = newListArray(n);
        queued = new boolean[n];
        wasQueued = new boolean[n];
        queue = new int[n];
        top = 0;

        // computes exception handlers for each instruction
        for (TryCatchBlockNode tcb : m.tryCatchBlocks) {
            int begin = insns.indexOf(tcb.start);
            int end = insns.indexOf(tcb.end);
            for (int j = begin; j < end; ++j) {
                List<TryCatchBlockNode> insnHandlers = handlers[j];
                if (insnHandlers == null) {
                    insnHandlers = new ArrayList<>();
                    handlers[j] = insnHandlers;
                }
                insnHandlers.add(tcb);
            }
        }

        merge(0);
        // control flow analysis
        while (top > 0) {
            int insn = queue[--top];

            queued[insn] = false;

            AbstractInsnNode insnNode = null;
            try {
                insnNode = m.instructions.get(insn);
                int insnOpcode = insnNode.getOpcode();
                int insnType = insnNode.getType();

                if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
                    merge(insn + 1);
                    myEdgeCreator.newControlFlowEdge(insn, insn + 1);
                }
                else {

                    if (insnNode instanceof JumpInsnNode) {
                        JumpInsnNode j = (JumpInsnNode) insnNode;
                        if (insnOpcode != GOTO && insnOpcode != JSR) {
                            merge(insn + 1);
                            myEdgeCreator.newControlFlowEdge(insn, insn + 1);
                        }
                        int jump = insns.indexOf(j.label);
                        if (insnOpcode == JSR) {
                            throw new AnalyzerException(insnNode, "ret is not supported");
                        }
                        else {
                            merge(jump);
                        }
                        myEdgeCreator.newControlFlowEdge(insn, jump);
                    }
                    else if (insnNode instanceof LookupSwitchInsnNode) {
                        LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
                        int jump = insns.indexOf(lsi.dflt);
                        merge(jump);
                        myEdgeCreator.newControlFlowEdge(insn, jump);
                        for (int j = 0; j < lsi.labels.size(); ++j) {
                            LabelNode label = lsi.labels.get(j);
                            jump = insns.indexOf(label);
                            merge(jump);
                            myEdgeCreator.newControlFlowEdge(insn, jump);
                        }
                    }
                    else if (insnNode instanceof TableSwitchInsnNode) {
                        TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
                        int jump = insns.indexOf(tsi.dflt);
                        merge(jump);
                        myEdgeCreator.newControlFlowEdge(insn, jump);
                        for (int j = 0; j < tsi.labels.size(); ++j) {
                            LabelNode label = tsi.labels.get(j);
                            jump = insns.indexOf(label);
                            merge(jump);
                            myEdgeCreator.newControlFlowEdge(insn, jump);
                        }
                    }
                    else if (insnOpcode == RET) {
                        throw new AnalyzerException(insnNode, "ret is not supported");
                    }
                    else if (insnOpcode != ATHROW && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
                        merge(insn + 1);
                        myEdgeCreator.newControlFlowEdge(insn, insn + 1);
                    }
                }

                List<TryCatchBlockNode> insnHandlers = handlers[insn];
                if (insnHandlers != null) {
                    for (TryCatchBlockNode tcb : insnHandlers) {
                        myEdgeCreator.newControlFlowExceptionEdge(insn, insns.indexOf(tcb.handler), NPE_HANDLERS.contains(tcb.type));
                        merge(insns.indexOf(tcb.handler));
                    }
                }
            }
            catch (AnalyzerException e) {
                throw new AnalyzerException(e.node, "Error at instruction " + insn + ": " + e.getMessage(), e);
            }
            catch (Exception e) {
                throw new AnalyzerException(insnNode, "Error at instruction " + insn + ": " + e.getMessage(), e);
            }
        }
    }

    // -------------------------------------------------------------------------

    protected void merge(int insn) {
        boolean changes = false;

        if (!wasQueued[insn]) {
            wasQueued[insn] = true;
            changes = true;
        }

        if (changes && !queued[insn]) {
            queued[insn] = true;
            queue[top++] = insn;
        }
    }

    public static <V> List<V>[] newListArray(int size) {
        @SuppressWarnings("unchecked")
        List<V>[] a = (List<V>[]) new List[size];
        return a;
    }
}

================================================
FILE: src/main/java/lsieun/asm/analysis/cfg/SimpleEdgeCreator.java
================================================
package lsieun.asm.analysis.cfg;

import lsieun.trove.TIntArrayList;

public class SimpleEdgeCreator implements EdgeCreator {
    public final TIntArrayList[] transitions;
    public final TIntArrayList[] errorTransitions;

    public SimpleEdgeCreator(int size) {
        this.transitions = new TIntArrayList[size];
        this.errorTransitions = new TIntArrayList[size];
        for (int i = 0; i < transitions.length; i++) {
            this.transitions[i] = new TIntArrayList();
            this.errorTransitions[i] = new TIntArrayList();
        }
    }

    @Override
    public void newControlFlowEdge(int insn, int successor) {
        if (!transitions[insn].contains(successor)) {
            transitions[insn].add(successor);
        }
    }

    @Override
    public void newControlFlowExceptionEdge(int insn, int successor, boolean npe) {
        if (!errorTransitions[insn].contains(successor)) {
            errorTransitions[insn].add(successor);
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/diagnosis/DeadCodeDiagnosis.java
================================================
package lsieun.asm.analysis.diagnosis;

import lsieun.asm.analysis.ControlFlowAnalyzer;
import lsieun.trove.TIntArrayList;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.AnalyzerException;

public class DeadCodeDiagnosis {
    public static int[] diagnose(String className, MethodNode mn) throws AnalyzerException {
        InsnList instructions = mn.instructions;
        int size = instructions.size();

        boolean[] flags = new boolean[size];
        ControlFlowAnalyzer analyzer = new ControlFlowAnalyzer() {
            @Override
            protected void newControlFlowEdge(int insnIndex, int successorIndex) {
                // 首先,处理自己的代码逻辑
                flags[insnIndex] = true;
                flags[successorIndex] = true;

                // 其次,调用父类的实现
                super.newControlFlowEdge(insnIndex, successorIndex);
            }
        };
        analyzer.analyze(className, mn);


        TIntArrayList intArrayList = new TIntArrayList();
        for (int i = 0; i < size; i++) {
            boolean flag = flags[i];
            if (!flag) {
                intArrayList.add(i);
            }
        }

        return intArrayList.toNativeArray();
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/diagnosis/NullDereferenceDiagnosis.java
================================================
package lsieun.asm.analysis.diagnosis;

import lsieun.asm.analysis.nullability.NullDeferenceInterpreter;
import lsieun.trove.TIntArrayList;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.*;

import java.util.Arrays;

import static org.objectweb.asm.Opcodes.*;

public class NullDereferenceDiagnosis {
    public static int[] diagnose(String owner, MethodNode mn) throws AnalyzerException {
        // 第一步,获取Frame信息
        Analyzer<BasicValue> analyzer = new Analyzer<>(new NullDeferenceInterpreter(ASM9));
        Frame<BasicValue>[] frames = analyzer.analyze(owner, mn);

        // 第二步,判断是否为null或maybe-null,收集数据
        TIntArrayList intArrayList = new TIntArrayList();
        InsnList instructions = mn.instructions;
        int size = instructions.size();
        for (int i = 0; i < size; i++) {
            AbstractInsnNode insn = instructions.get(i);
            if (frames[i] != null) {
                Value value = getTarget(insn, frames[i]);
                if (value == NullDeferenceInterpreter.NULL_VALUE || value == NullDeferenceInterpreter.MAYBE_NULL_VALUE) {
                    intArrayList.add(i);
                }
            }
        }

        // 第三步,将结果转换成int[]形式
        int[] array = intArrayList.toNativeArray();
        Arrays.sort(array);
        return array;
    }

    private static BasicValue getTarget(AbstractInsnNode insn, Frame<BasicValue> frame) {
        int opcode = insn.getOpcode();
        switch (opcode) {
            case GETFIELD:
            case ARRAYLENGTH:
            case MONITORENTER:
            case MONITOREXIT:
                return getStackValue(frame, 0);
            case PUTFIELD:
                return getStackValue(frame, 1);
            case INVOKEVIRTUAL:
            case INVOKESPECIAL:
            case INVOKEINTERFACE:
                String desc = ((MethodInsnNode) insn).desc;
                return getStackValue(frame, Type.getArgumentTypes(desc).length);

        }
        return null;
    }

    private static BasicValue getStackValue(Frame<BasicValue> frame, int index) {
        int top = frame.getStackSize() - 1;
        return index <= top ? frame.getStack(top - index) : null;
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/diagnosis/NullabilityDiagnosis.java
================================================
package lsieun.asm.analysis.diagnosis;

import lsieun.asm.analysis.nullability.Nullability;
import lsieun.asm.analysis.nullability.NullabilityAnalyzer;
import lsieun.asm.analysis.nullability.NullabilityInterpreter;
import lsieun.asm.analysis.nullability.NullabilityValue;
import lsieun.trove.TIntArrayList;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.analysis.Analyzer;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.Frame;

import java.util.Arrays;

import static org.objectweb.asm.Opcodes.*;

public class NullabilityDiagnosis {
    public static int[] diagnose(String className, MethodNode mn) throws AnalyzerException {
        // 第一步,获取Frame信息
        Analyzer<NullabilityValue> analyzer = new NullabilityAnalyzer(new NullabilityInterpreter(Opcodes.ASM9));
        Frame<NullabilityValue>[] frames = analyzer.analyze(className, mn);

        // 第二步,判断是否为null或maybe-null,收集数据
        TIntArrayList intArrayList = new TIntArrayList();
        InsnList instructions = mn.instructions;
        int size = instructions.size();
        for (int i = 0; i < size; i++) {
            AbstractInsnNode insn = instructions.get(i);
            if (frames[i] != null) {
                NullabilityValue value = getTarget(insn, frames[i]);
                if (value == null) continue;
                if (value.getState() == Nullability.NULL || value.getState() == Nullability.NULLABLE) {
                    intArrayList.add(i);
                }
            }
        }

        // 第三步,将结果转换成int[]形式
        int[] array = intArrayList.toNativeArray();
        Arrays.sort(array);
        return array;
    }

    private static NullabilityValue getTarget(AbstractInsnNode insn, Frame<NullabilityValue> frame) {
        int opcode = insn.getOpcode();
        switch (opcode) {
            case GETFIELD:
            case ARRAYLENGTH:
            case MONITORENTER:
            case MONITOREXIT:
                return getStackValue(frame, 0);
            case PUTFIELD:
                return getStackValue(frame, 1);
            case INVOKEVIRTUAL:
            case INVOKESPECIAL:
            case INVOKEINTERFACE:
                String desc = ((MethodInsnNode) insn).desc;
                return getStackValue(frame, Type.getArgumentTypes(desc).length);

        }
        return null;
    }

    private static NullabilityValue getStackValue(Frame<NullabilityValue> frame, int index) {
        int top = frame.getStackSize() - 1;
        return index <= top ? frame.getStack(top - index) : null;
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/diagnosis/RedundantVariableDiagnosis.java
================================================
package lsieun.asm.analysis.diagnosis;

import lsieun.trove.TIntArrayList;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
import org.objectweb.asm.tree.analysis.*;

import java.util.Arrays;

public class RedundantVariableDiagnosis {
    public static int[] diagnose(String className, MethodNode mn) throws AnalyzerException {
        // 第一步,准备工作。使用SimpleVerifier进行分析,得到frames信息
        Analyzer<BasicValue> analyzer = new Analyzer<>(new SimpleVerifier());
        Frame<BasicValue>[] frames = analyzer.analyze(className, mn);

        // 第二步,利用frames信息,查看local variable当中哪些slot数据出现了冗余
        TIntArrayList localIndexList = new TIntArrayList();
        for (Frame<BasicValue> f : frames) {
            int locals = f.getLocals();
            for (int i = 0; i < locals; i++) {
                BasicValue val1 = f.getLocal(i);
                if (val1 == BasicValue.UNINITIALIZED_VALUE) {
                    continue;
                }
                for (int j = i + 1; j < locals; j++) {
                    BasicValue val2 = f.getLocal(j);
                    if (val2 == BasicValue.UNINITIALIZED_VALUE) {
                        continue;
                    }
                    if (val1 == val2) {
                        if (!localIndexList.contains(j)) {
                            localIndexList.add(j);
                        }
                    }
                }
            }
        }

        // 第三步,将slot的索引值(local index)转换成instruction的索引值(insn index)
        TIntArrayList insnIndexList = new TIntArrayList();
        InsnList instructions = mn.instructions;
        int size = instructions.size();
        for (int i = 0; i < size; i++) {
            AbstractInsnNode node = instructions.get(i);
            int opcode = node.getOpcode();
            if (opcode >= Opcodes.ISTORE && opcode <= Opcodes.ASTORE) {
                VarInsnNode varInsnNode = (VarInsnNode) node;
                if (localIndexList.contains(varInsnNode.var)) {
                    if (!insnIndexList.contains(i)) {
                        insnIndexList.add(i);
                    }
                }
            }
        }

        // 第四步,将insnIndexList转换成int[]形式
        int[] array = insnIndexList.toNativeArray();
        Arrays.sort(array);
        return array;
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/diagnosis/RelatedInstructionDiagnosis.java
================================================
package lsieun.asm.analysis.diagnosis;

import lsieun.asm.analysis.transition.DestinationInterpreter;
import lsieun.trove.TIntArrayList;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
import org.objectweb.asm.tree.analysis.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class RelatedInstructionDiagnosis {
    public static int[] diagnose(String className, MethodNode mn, int insnIndex) throws AnalyzerException {
        // 第一步,判断insnIndex范围是否合理
        InsnList instructions = mn.instructions;
        int size = instructions.size();
        if (insnIndex < 0 || insnIndex >= size) {
            String message = String.format("the 'insnIndex' argument should in range [0, %d]", size - 1);
            throw new IllegalArgumentException(message);
        }

        // 第二步,获取两个Frame
        Frame<SourceValue>[] sourceFrames = getSourceFrames(className, mn);
        Frame<SourceValue>[] destinationFrames = getDestinationFrames(className, mn);

        // 第三步,循环处理,所有结果记录到这个intArrayList变量中
        TIntArrayList intArrayList = new TIntArrayList();
        // 循环tmpInsnList
        List<AbstractInsnNode> tmpInsnList = new ArrayList<>();
        AbstractInsnNode insnNode = instructions.get(insnIndex);
        tmpInsnList.add(insnNode);
        for (int i = 0; i < tmpInsnList.size(); i++) {
            AbstractInsnNode currentNode = tmpInsnList.get(i);
            int opcode = currentNode.getOpcode();

            int index = instructions.indexOf(currentNode);
            intArrayList.add(index);

            // 第一种情况,处理load相关的opcode情况
            Frame<SourceValue> srcFrame = sourceFrames[index];
            if (opcode >= Opcodes.ILOAD && opcode <= Opcodes.ALOAD) {
                VarInsnNode varInsnNode = (VarInsnNode) currentNode;
                int localIndex = varInsnNode.var;
                SourceValue value = srcFrame.getLocal(localIndex);
                for (AbstractInsnNode insn : value.insns) {
                    if (!tmpInsnList.contains(insn)) {
                        tmpInsnList.add(insn);
                    }
                }
            }

            // 第二种情况,从dstFrame到srcFrame查找
            Frame<SourceValue> dstFrame = destinationFrames[index];
            int stackSize = dstFrame.getStackSize();
            for (int j = 0; j < stackSize; j++) {
                SourceValue value = dstFrame.getStack(j);
                if (value.insns.contains(currentNode)) {
                    for (AbstractInsnNode insn : srcFrame.getStack(j).insns) {
                        if (!tmpInsnList.contains(insn)) {
                            tmpInsnList.add(insn);
                        }
                    }
                }
            }
        }

        // 第四步,将intArrayList变量转换成int[],并进行排序
        int[] array = intArrayList.toNativeArray();
        Arrays.sort(array);
        return array;
    }


    private static Frame<SourceValue>[] getSourceFrames(String className, MethodNode mn) throws AnalyzerException {
        Analyzer<SourceValue> analyzer = new Analyzer<>(new SourceInterpreter());
        return analyzer.analyze(className, mn);
    }

    private static Frame<SourceValue>[] getDestinationFrames(String className, MethodNode mn) throws AnalyzerException {
        Analyzer<SourceValue> analyzer = new Analyzer<>(new DestinationInterpreter());
        return analyzer.analyze(className, mn);
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/diagnosis/ReverseEngineerMethodArgumentsDiagnosis.java
================================================
package lsieun.asm.analysis.diagnosis;

import org.objectweb.asm.Type;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.analysis.*;

import java.util.ArrayList;
import java.util.List;

public class ReverseEngineerMethodArgumentsDiagnosis {
    private static final String UNKNOWN_VARIABLE_NAME = "unknown";

    public static void diagnose(String className, MethodNode mn) throws AnalyzerException {
        // 第一步,获取Frame信息
        Analyzer<SourceValue> analyzer = new Analyzer<>(new SourceInterpreter());
        Frame<SourceValue>[] frames = analyzer.analyze(className, mn);

        // 第二步,获取LocalVariableTable信息
        List<LocalVariableNode> localVariables = mn.localVariables;
        if (localVariables == null || localVariables.size() < 1) {
            System.out.println("LocalVariableTable is Empty");
            return;
        }

        // 第三步,获取instructions,并找到与invoke相关的指令
        InsnList instructions = mn.instructions;
        int[] methodInsnArray = findMethodInvokes(instructions);

        // 第四步,对invoke相关的指令进行反编译
        for (int methodInsn : methodInsnArray) {
            // (1) 获取方法的参数
            MethodInsnNode methodInsnNode = (MethodInsnNode) instructions.get(methodInsn);
            Type methodType = Type.getMethodType(methodInsnNode.desc);
            Type[] argumentTypes = methodType.getArgumentTypes();
            int argNum = argumentTypes.length;

            // (2) 从Frame当中获取指令,并将指令转换LocalVariableTable当中的变量名
            Frame<SourceValue> f = frames[methodInsn];
            int stackSize = f.getStackSize();
            List<String> argList = new ArrayList<>();
            for (int i = 0; i < argNum; i++) {
                int stackIndex = stackSize - argNum + i;
                SourceValue stackValue = f.getStack(stackIndex);
                AbstractInsnNode insn = stackValue.insns.iterator().next();
                String argName = getMethodVariableName(insn, localVariables);
                argList.add(argName);
            }

            // (3) 将反编译的结果打印出来
            String line = String.format("%s.%s(%s)", methodInsnNode.owner, methodInsnNode.name, argList);
            System.out.println(line);
        }
    }

    public static String getMethodVariableName(AbstractInsnNode insn, List<LocalVariableNode> localVariables) {
        if (insn instanceof VarInsnNode) {
            VarInsnNode varInsnNode = (VarInsnNode) insn;
            int localIndex = varInsnNode.var;

            for (LocalVariableNode node : localVariables) {
                if (node.index == localIndex) {
                    return node.name;
                }
            }

            return String.format("locals[%d]", localIndex);
        }
        return UNKNOWN_VARIABLE_NAME;
    }

    public static int[] findMethodInvokes(InsnList instructions) {
        int size = instructions.size();
        boolean[] methodArray = new boolean[size];
        for (int i = 0; i < size; i++) {
            AbstractInsnNode node = instructions.get(i);
            if (node instanceof MethodInsnNode) {
                methodArray[i] = true;
            }
        }

        int count = 0;
        for (boolean flag : methodArray) {
            if (flag) {
                count++;
            }
        }

        int[] array = new int[count];
        int j = 0;
        for (int i = 0; i < size; i++) {
            boolean flag = methodArray[i];
            if (flag) {
                array[j] = i;
                j++;
            }
        }
        return array;
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/graph/InsnBlock.java
================================================
package lsieun.asm.analysis.graph;

import java.util.ArrayList;
import java.util.List;

public class InsnBlock {
    // 文字信息
    public final List<String> lines = new ArrayList<>();

    // 关联关系
    public final List<InsnBlock> nextBlockList = new ArrayList<>();
    public final List<InsnBlock> jumpBlockList = new ArrayList<>();

    public void addLines(List<String> list) {
        lines.addAll(list);
    }

    public void addNext(InsnBlock item) {
        if (!nextBlockList.contains(item)) {
            nextBlockList.add(item);
        }
    }

    public void addJump(InsnBlock item) {
        if (!jumpBlockList.contains(item)) {
            jumpBlockList.add(item);
        }
    }

}


================================================
FILE: src/main/java/lsieun/asm/analysis/graph/TextBox.java
================================================
package lsieun.asm.analysis.graph;

public class TextBox {
    public final int row;
    public final int col;
    public final int width;
    public final int height;

    public TextBox(int row, int col, int width, int height) {
        this.row = row;
        this.col = col;
        this.width = width;
        this.height = height;
    }

    public static TextBox valueOf(int row, int col, int width, int height) {
        return new TextBox(row, col, width, height);
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/graph/TextGraph.java
================================================
package lsieun.asm.analysis.graph;

import lsieun.drawing.canvas.Box;
import lsieun.drawing.canvas.Canvas;
import lsieun.drawing.canvas.TextDirection;
import lsieun.drawing.theme.line.ContinuousLine;
import lsieun.drawing.theme.text.PlainText;

import java.util.ArrayList;
import java.util.List;

public class TextGraph {
    private static final int ROW_SPACE = 1;
    private static final int COL_SPACE = 3;

    private final InsnBlock[] blockArray;
    private final TextBox[] boxArray;
    private final int boxNum;
    private final int maxInstructionLength;
    private final Canvas canvas = new Canvas();

    public TextGraph(InsnBlock[] blockArray) {
        this.blockArray = blockArray;
        this.boxNum = blockArray.length;
        this.boxArray = new TextBox[boxNum];
        this.maxInstructionLength = findMaxStringLength(blockArray);
    }

    @SuppressWarnings("UnnecessaryLocalVariable")
    public void draw(int startRow, int startCol) {
        int row = startRow;
        int col = startCol;
        int length = boxArray.length;
        for (int i = 0; i < length; i++) {
            InsnBlock block = blockArray[i];

            int width = getOdd(maxInstructionLength + 2);
            int height = block.lines.size();

            TextBox box = TextBox.valueOf(row, col, width, height);
            boxArray[i] = box;
            drawBoxAndText(box, block.lines);

            row += height + ROW_SPACE + 2;
        }

        drawLinks();

        System.out.println(canvas);
    }

    private void drawBoxAndText(TextBox box, List<String> lines) {
        int row = box.row;
        int col = box.col;
        int width = box.width;
        int height = box.height;

        canvas.moveTo(row, col);
        canvas.drawRectangle(width, height);
        canvas.draw(row + 1, col + 2, PlainText.valueOf(lines));
    }

    private void drawLinks() {
        for (int i = 0; i < boxNum; i++) {
            InsnBlock currentBlock = blockArray[i];
            TextBox currentBox = boxArray[i];

            // draw next
            List<TextBox> nextBoxes = findBoxes(currentBlock.nextBlockList);
            for (TextBox nextBox : nextBoxes) {
                int rowStart = currentBox.row + currentBox.height + 1;
                int rowStop = nextBox.row;
                int col = currentBox.col + currentBox.width / 2;

                canvas.moveTo(rowStart, col);
                canvas.drawPixel(Box.DOWN_AND_HORIZONTAL);
                canvas.moveTo(rowStop, col);
                canvas.drawPixel(Box.UP_AND_HORIZONTAL);
                canvas.moveTo(rowStart + 1, col).drawVerticalLine(rowStop - rowStart - 1);
            }

            // draw jump
            List<TextBox> jumpBoxes = findBoxes(currentBlock.jumpBlockList);
            for (TextBox nextBox : jumpBoxes) {
                int rowStart = currentBox.row + currentBox.height;
                int rowStop = nextBox.row + 1;
                int colStart = currentBox.col + currentBox.width + 1;
                int colStop = currentBox.col + currentBox.width + 1 + (i + 1) * COL_SPACE;

                canvas.moveTo(rowStart, colStart);
                canvas.drawPixel(Box.VERTICAL_AND_RIGHT);
                canvas.moveTo(rowStop, colStart);
                canvas.drawPixel(Box.VERTICAL_AND_RIGHT);

                if (rowStart < rowStop) {
                    ContinuousLine line = new ContinuousLine();
                    line.setDirection(TextDirection.RIGHT);
                    line.drawLine(colStop - colStart)
                            .turn(TextDirection.DOWN).drawLine(rowStop - rowStart - 1)
                            .turn(TextDirection.LEFT).drawLine(colStop - colStart);
                    canvas.draw(rowStart, colStart + 1, line);

                }
                else {
                    ContinuousLine line = new ContinuousLine();
                    line.setDirection(TextDirection.RIGHT);
                    line.drawLine(colStop - colStart)
                            .turn(TextDirection.UP).drawLine(rowStart - rowStop - 1)
                            .turn(TextDirection.LEFT).drawLine(colStop - colStart);
                    canvas.draw(rowStart, colStart + 1, line);
                }
            }
        }
    }

    private List<TextBox> findBoxes(List<InsnBlock> blockList) {
        List<TextBox> boxList = new ArrayList<>();

        for (int i = 0; i < boxNum; i++) {
            InsnBlock block = blockArray[i];
            if (blockList.contains(block)) {
                boxList.add(boxArray[i]);
            }
        }

        return boxList;
    }

    private int getOdd(int num) {
        int remainder = num % 2;
        if (remainder == 0) {
            return num + 1;
        }
        return num;
    }

    private int findMaxStringLength(InsnBlock[] blockArray) {
        int maxLength = 0;
        for (InsnBlock block : blockArray) {
            int length = findMaxStringLength(block.lines);
            if (length > maxLength) {
                maxLength = length;
            }
        }
        return maxLength;
    }

    private int findMaxStringLength(List<String> lines) {
        int maxLength = 0;
        for (String item : lines) {
            if (item == null) continue;
            int length = item.length();
            if (length > maxLength) {
                maxLength = length;
            }
        }
        return maxLength;
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/nullability/NullDeferenceInterpreter.java
================================================
package lsieun.asm.analysis.nullability;

import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.BasicInterpreter;
import org.objectweb.asm.tree.analysis.BasicValue;
import org.objectweb.asm.tree.analysis.Value;

public class NullDeferenceInterpreter extends BasicInterpreter {
    public final static BasicValue NULL_VALUE = new BasicValue(NULL_TYPE);
    public final static BasicValue MAYBE_NULL_VALUE = new BasicValue(Type.getObjectType("may-be-null"));

    public NullDeferenceInterpreter(int api) {
        super(api);
    }

    @Override
    public BasicValue newOperation(AbstractInsnNode insn) throws AnalyzerException {
        if (insn.getOpcode() == ACONST_NULL) {
            return NULL_VALUE;
        }
        return super.newOperation(insn);
    }

    @Override
    public BasicValue merge(BasicValue value1, BasicValue value2) {
        if (isRef(value1) && isRef(value2) && value1 != value2) {
            return MAYBE_NULL_VALUE;
        }
        return super.merge(value1, value2);
    }

    private boolean isRef(Value value) {
        return value == BasicValue.REFERENCE_VALUE || value == NULL_VALUE || value == MAYBE_NULL_VALUE;
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/nullability/Nullability.java
================================================
package lsieun.asm.analysis.nullability;

public enum Nullability {
    UNKNOWN(0),
    NOT_NULL(1),
    NULL(1),
    NULLABLE(2);

    public final int priority;

    Nullability(int priority) {
        this.priority = priority;
    }

    public static Nullability merge(Nullability value1, Nullability value2) {
        // 第一种情况,两者相等,则直接返回一个
        if (value1 == value2) {
            return value1;
        }

        // 第二种情况,两者不相等,比较优先级大小,谁大返回谁
        int priority1 = value1.priority;
        int priority2 = value2.priority;
        if (priority1 > priority2) {
            return value1;
        }
        else if (priority1 < priority2) {
            return value2;
        }

        // 第三种情况,两者不相等,但优先级相等,则一个是NOT_NULL,另一个是NULL
        return NULLABLE;
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/nullability/NullabilityAnalyzer.java
================================================
package lsieun.asm.analysis.nullability;

import org.objectweb.asm.tree.analysis.Analyzer;
import org.objectweb.asm.tree.analysis.Frame;
import org.objectweb.asm.tree.analysis.Interpreter;

public class NullabilityAnalyzer extends Analyzer<NullabilityValue> {
    public NullabilityAnalyzer(Interpreter<NullabilityValue> interpreter) {
        super(interpreter);
    }

    @Override
    protected Frame<NullabilityValue> newFrame(Frame<? extends NullabilityValue> frame) {
        return new NullabilityFrame((NullabilityFrame) frame);
    }

    @Override
    protected Frame<NullabilityValue> newFrame(int numLocals, int numStack) {
        return new NullabilityFrame(numLocals, numStack);
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/nullability/NullabilityFrame.java
================================================
package lsieun.asm.analysis.nullability;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.analysis.Frame;

public class NullabilityFrame extends Frame<NullabilityValue> {
    public NullabilityFrame(int numLocals, int numStack) {
        super(numLocals, numStack);
    }

    public NullabilityFrame(NullabilityFrame frame) {
        super(frame);
    }

    @Override
    public void initJumpTarget(int opcode, LabelNode target) {
        // 首先,处理自己的代码逻辑
        int stackIndex = getStackSize();
        NullabilityValue oldValue = getStack(stackIndex);
        switch (opcode) {
            case Opcodes.IFNULL: {
                if (target == null) {
                    updateFrame(oldValue, Nullability.NOT_NULL);
                }
                else {
                    updateFrame(oldValue, Nullability.NULL);
                }
                break;
            }
            case Opcodes.IFNONNULL: {
                if (target == null) {
                    updateFrame(oldValue, Nullability.NULL);
                }
                else {
                    updateFrame(oldValue, Nullability.NOT_NULL);
                }
                break;
            }
        }

        // 其次,调用父类的方法实现
        super.initJumpTarget(opcode, target);
    }

    private void updateFrame(NullabilityValue oldValue, Nullability newState) {
        NullabilityValue newValue = new NullabilityValue(oldValue.getType(), newState);
        int numLocals = getLocals();
        for (int i = 0; i < numLocals; i++) {
            NullabilityValue currentValue = getLocal(i);
            if (oldValue == currentValue) {
                setLocal(i, newValue);
            }
        }

        int numStack = getMaxStackSize();
        for (int i = 0; i < numStack; i++) {
            NullabilityValue currentValue = getStack(i);
            if (oldValue == currentValue) {
                setStack(i, newValue);
            }
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/nullability/NullabilityInterpreter.java
================================================
package lsieun.asm.analysis.nullability;

import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.Interpreter;

import java.util.List;

public class NullabilityInterpreter extends Interpreter<NullabilityValue> implements Opcodes {
    public static final Type NULL_TYPE = Type.getObjectType("null");

    public static final NullabilityValue UNINITIALIZED_VALUE = new NullabilityValue(null);
    public static final NullabilityValue RETURN_ADDRESS_VALUE = new NullabilityValue(Type.VOID_TYPE);

    private final ClassLoader loader = getClass().getClassLoader();

    public NullabilityInterpreter(int api) {
        super(api);
    }

    @Override
    public NullabilityValue newValue(Type type) {
        if (type == null) {
            return UNINITIALIZED_VALUE;
        }

        int sort = type.getSort();
        if (sort == Type.VOID) {
            return null;
        }
        return new NullabilityValue(type);
    }

    @Override
    public NullabilityValue newOperation(AbstractInsnNode insn) throws AnalyzerException {
        switch (insn.getOpcode()) {
            case ACONST_NULL:
                return new NullabilityValue(NULL_TYPE, Nullability.NULL);
            case ICONST_M1:
            case ICONST_0:
            case ICONST_1:
            case ICONST_2:
            case ICONST_3:
            case ICONST_4:
            case ICONST_5:
            case BIPUSH:
            case SIPUSH:
                return newValue(Type.INT_TYPE);
            case LCONST_0:
            case LCONST_1:
                return newValue(Type.LONG_TYPE);
            case FCONST_0:
            case FCONST_1:
            case FCONST_2:
                return newValue(Type.FLOAT_TYPE);
            case DCONST_0:
            case DCONST_1:
                return newValue(Type.DOUBLE_TYPE);
            case LDC:
                Object value = ((LdcInsnNode) insn).cst;
                if (value instanceof Integer) {
                    return newValue(Type.INT_TYPE);
                }
                else if (value instanceof Float) {
                    return newValue(Type.FLOAT_TYPE);
                }
                else if (value instanceof Long) {
                    return newValue(Type.LONG_TYPE);
                }
                else if (value instanceof Double) {
                    return newValue(Type.DOUBLE_TYPE);
                }
                else if (value instanceof String) {
                    return new NullabilityValue(Type.getObjectType("java/lang/String"), Nullability.NOT_NULL);
                }
                else if (value instanceof Type) {
                    int sort = ((Type) value).getSort();
                    if (sort == Type.OBJECT || sort == Type.ARRAY) {
                        return newValue(Type.getObjectType("java/lang/Class"));
                    }
                    else if (sort == Type.METHOD) {
                        return newValue(Type.getObjectType("java/lang/invoke/MethodType"));
                    }
                    else {
                        throw new AnalyzerException(insn, "Illegal LDC value " + value);
                    }
                }
                else if (value instanceof Handle) {
                    return newValue(Type.getObjectType("java/lang/invoke/MethodHandle"));
                }
                else if (value instanceof ConstantDynamic) {
                    return newValue(Type.getType(((ConstantDynamic) value).getDescriptor()));
                }
                else {
                    throw new AnalyzerException(insn, "Illegal LDC value " + value);
                }
            case JSR:
                return RETURN_ADDRESS_VALUE;
            case GETSTATIC:
                return newValue(Type.getType(((FieldInsnNode) insn).desc));
            case NEW:
                return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
            default:
                throw new AssertionError();
        }
    }

    @Override
    public NullabilityValue copyOperation(AbstractInsnNode insn, NullabilityValue value) {
        return value;
    }

    @Override
    public NullabilityValue unaryOperation(AbstractInsnNode insn, NullabilityValue value) throws AnalyzerException {
        switch (insn.getOpcode()) {
            case INEG:
            case IINC:
            case L2I:
            case F2I:
            case D2I:
            case I2B:
            case I2C:
            case I2S:
            case ARRAYLENGTH:
            case INSTANCEOF:
                return newValue(Type.INT_TYPE);
            case FNEG:
            case I2F:
            case L2F:
            case D2F:
                return newValue(Type.FLOAT_TYPE);
            case LNEG:
            case I2L:
            case F2L:
            case D2L:
                return newValue(Type.LONG_TYPE);
            case DNEG:
            case I2D:
            case L2D:
            case F2D:
                return newValue(Type.DOUBLE_TYPE);
            case GETFIELD:
                return newValue(Type.getType(((FieldInsnNode) insn).desc));
            case NEWARRAY:
                switch (((IntInsnNode) insn).operand) {
                    case T_BOOLEAN:
                        return newValue(Type.getType("[Z"));
                    case T_CHAR:
                        return newValue(Type.getType("[C"));
                    case T_BYTE:
                        return newValue(Type.getType("[B"));
                    case T_SHORT:
                        return newValue(Type.getType("[S"));
                    case T_INT:
                        return newValue(Type.getType("[I"));
                    case T_FLOAT:
                        return newValue(Type.getType("[F"));
                    case T_DOUBLE:
                        return newValue(Type.getType("[D"));
                    case T_LONG:
                        return newValue(Type.getType("[J"));
                    default:
                        break;
                }
                throw new AnalyzerException(insn, "Invalid array type");
            case ANEWARRAY:
                return newValue(Type.getType("[" + Type.getObjectType(((TypeInsnNode) insn).desc)));
            case CHECKCAST:
                return value;
            case IFEQ:
            case IFNE:
            case IFLT:
            case IFGE:
            case IFGT:
            case IFLE:
            case TABLESWITCH:
            case LOOKUPSWITCH:
            case IRETURN:
            case LRETURN:
            case FRETURN:
            case DRETURN:
            case ARETURN:
            case PUTSTATIC:
            case ATHROW:
            case MONITORENTER:
            case MONITOREXIT:
            case IFNULL:
            case IFNONNULL:
                return null;
            default:
                throw new AssertionError();
        }
    }

    @Override
    public NullabilityValue binaryOperation(AbstractInsnNode insn,
                                            NullabilityValue value1,
                                            NullabilityValue value2) {
        switch (insn.getOpcode()) {
            case IALOAD:
            case BALOAD:
            case CALOAD:
            case SALOAD:
            case IADD:
            case ISUB:
            case IMUL:
            case IDIV:
            case IREM:
            case ISHL:
            case ISHR:
            case IUSHR:
            case IAND:
            case IOR:
            case IXOR:
            case LCMP:
            case FCMPL:
            case FCMPG:
            case DCMPL:
            case DCMPG:
                return newValue(Type.INT_TYPE);
            case FALOAD:
            case FADD:
            case FSUB:
            case FMUL:
            case FDIV:
            case FREM:
                return newValue(Type.FLOAT_TYPE);
            case LALOAD:
            case LADD:
            case LSUB:
            case LMUL:
            case LDIV:
            case LREM:
            case LSHL:
            case LSHR:
            case LUSHR:
            case LAND:
            case LOR:
            case LXOR:
                return newValue(Type.LONG_TYPE);
            case DALOAD:
            case DADD:
            case DSUB:
            case DMUL:
            case DDIV:
            case DREM:
                return newValue(Type.LONG_TYPE);
            case AALOAD:
                return getElementValue(value1);
            case IF_ICMPEQ:
            case IF_ICMPNE:
            case IF_ICMPLT:
            case IF_ICMPGE:
            case IF_ICMPGT:
            case IF_ICMPLE:
            case IF_ACMPEQ:
            case IF_ACMPNE:
            case PUTFIELD:
                return null;
            default:
                throw new AssertionError();
        }
    }

    @Override
    public NullabilityValue ternaryOperation(AbstractInsnNode insn,
                                             NullabilityValue value1,
                                             NullabilityValue value2,
                                             NullabilityValue value3) {
        return null;
    }

    @Override
    public NullabilityValue naryOperation(AbstractInsnNode insn,
                                          List<? extends NullabilityValue> values) {
        int opcode = insn.getOpcode();
        if (opcode == MULTIANEWARRAY) {
            return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
        }
        else if (opcode == INVOKEDYNAMIC) {
            return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc));
        }
        else {
            return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
        }
    }

    @Override
    public void returnOperation(AbstractInsnNode insn,
                                NullabilityValue value,
                                NullabilityValue expected) {
        // Nothing to do.
    }

    @Override
    public NullabilityValue merge(NullabilityValue value1, NullabilityValue value2) {
        // 合并两者的状态
        Nullability mergedState = Nullability.merge(value1.getState(), value2.getState());


        // 第一种情况,两个value的类型相同且状态(state)相同
        if (value1.equals(value2)) {
            return value1;
        }

        // 第二种情况,两个value的类型相同,但状态(state)不同,需要合并它们的状态(state)
        Type type1 = value1.getType();
        Type type2 = value2.getType();
        if (type1 != null && type1.equals(type2)) {
            Type type = value1.getType();
            return new NullabilityValue(type, mergedState);
        }

        // 第三种情况,两个value的类型不相同的,而且要合并它们的状态(state)
        if (type1 != null
                && (type1.getSort() == Type.OBJECT || type1.getSort() == Type.ARRAY)
                && type2 != null
                && (type2.getSort() == Type.OBJECT || type2.getSort() == Type.ARRAY)) {
            if (type1.equals(NULL_TYPE)) {
                return new NullabilityValue(type2, mergedState);
            }
            if (type2.equals(NULL_TYPE)) {
                return new NullabilityValue(type1, mergedState);
            }
            if (isAssignableFrom(type1, type2)) {
                return new NullabilityValue(type1, mergedState);
            }
            if (isAssignableFrom(type2, type1)) {
                return new NullabilityValue(type2, mergedState);
            }
            int numDimensions = 0;
            if (type1.getSort() == Type.ARRAY
                    && type2.getSort() == Type.ARRAY
                    && type1.getDimensions() == type2.getDimensions()
                    && type1.getElementType().getSort() == Type.OBJECT
                    && type2.getElementType().getSort() == Type.OBJECT) {
                numDimensions = type1.getDimensions();
                type1 = type1.getElementType();
                type2 = type2.getElementType();
            }


            while (true) {
                if (type1 == null || isInterface(type1)) {
                    NullabilityValue arrayValue = newArrayValue(Type.getObjectType("java/lang/Object"), numDimensions);
                    return new NullabilityValue(arrayValue.getType(), mergedState);
                }
                type1 = getSuperClass(type1);
                if (isAssignableFrom(type1, type2)) {
                    NullabilityValue arrayValue = newArrayValue(type1, numDimensions);
                    return new NullabilityValue(arrayValue.getType(), mergedState);
                }
            }
        }
        return UNINITIALIZED_VALUE;
    }

    protected boolean isInterface(final Type type) {
        return getClass(type).isInterface();
    }

    protected Type getSuperClass(final Type type) {
        Class<?> superClass = getClass(type).getSuperclass();
        return superClass == null ? null : Type.getType(superClass);
    }

    private NullabilityValue newArrayValue(final Type type, final int dimensions) {
        if (dimensions == 0) {
            return newValue(type);
        }
        else {
            StringBuilder descriptor = new StringBuilder();
            for (int i = 0; i < dimensions; ++i) {
                descriptor.append('[');
            }
            descriptor.append(type.getDescriptor());
            return newValue(Type.getType(descriptor.toString()));
        }
    }

    protected NullabilityValue getElementValue(final NullabilityValue objectArrayValue) {
        Type arrayType = objectArrayValue.getType();
        if (arrayType != null) {
            if (arrayType.getSort() == Type.ARRAY) {
                return newValue(Type.getType(arrayType.getDescriptor().substring(1)));
            }
            else if (arrayType.equals(NULL_TYPE)) {
                return objectArrayValue;
            }
        }
        throw new AssertionError();
    }

    protected boolean isSubTypeOf(final NullabilityValue value, final NullabilityValue expected) {
        Type expectedType = expected.getType();
        Type type = value.getType();
        switch (expectedType.getSort()) {
            case Type.INT:
            case Type.FLOAT:
            case Type.LONG:
            case Type.DOUBLE:
                return type.equals(expectedType);
            case Type.ARRAY:
            case Type.OBJECT:
                if (type.equals(NULL_TYPE)) {
                    return true;
                }
                else if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
                    if (isAssignableFrom(expectedType, type)) {
                        return true;
                    }
                    else if (getClass(expectedType).isInterface()) {
                        // The merge of class or interface types can only yield class types (because it is not
                        // possible in general to find an unambiguous common super interface, due to multiple
                        // inheritance). Because of this limitation, we need to relax the subtyping check here
                        // if 'value' is an interface.
                        return Object.class.isAssignableFrom(getClass(type));
                    }
                    else {
                        return false;
                    }
                }
                else {
                    return false;
                }
            default:
                throw new AssertionError();
        }
    }

    protected boolean isAssignableFrom(final Type type1, final Type type2) {
        if (type1.equals(type2)) {
            return true;
        }
        return getClass(type1).isAssignableFrom(getClass(type2));
    }

    protected Class<?> getClass(final Type type) {
        try {
            if (type.getSort() == Type.ARRAY) {
                return Class.forName(type.getDescriptor().replace('/', '.'), false, loader);
            }
            return Class.forName(type.getClassName(), false, loader);
        }
        catch (ClassNotFoundException e) {
            throw new TypeNotPresentException(e.toString(), e);
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/nullability/NullabilityValue.java
================================================
package lsieun.asm.analysis.nullability;

import org.objectweb.asm.Type;
import org.objectweb.asm.tree.analysis.Value;

public class NullabilityValue implements Value {
    private final Type type;
    private Nullability state;

    public NullabilityValue(Type type) {
        this(type, Nullability.UNKNOWN);
    }

    public NullabilityValue(Type type, Nullability state) {
        this.type = type;
        this.state = state;
    }

    public Type getType() {
        return type;
    }

    public void setState(Nullability state) {
        this.state = state;
    }

    public Nullability getState() {
        return state;
    }

    @Override
    public int getSize() {
        return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1;
    }

    public boolean isReference() {
        return type != null && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY);
    }

    @Override
    public boolean equals(final Object value) {
        if (value == this) {
            return true;
        }
        else if (value instanceof NullabilityValue) {
            NullabilityValue another = (NullabilityValue) value;
            if (type == null) {
                return ((NullabilityValue) value).type == null;
            }
            else {
                return type.equals(((NullabilityValue) value).type) && state == another.state;
            }
        }
        else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return type == null ? 0 : type.hashCode();
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/state/StateInterpreter.java
================================================
package lsieun.asm.analysis.state;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.Interpreter;

import java.util.List;

public class StateInterpreter extends Interpreter<StateValue> implements Opcodes {
    public StateInterpreter() {
        super(ASM9);
        if (getClass() != StateInterpreter.class) {
            throw new IllegalStateException();
        }
    }

    public StateInterpreter(int api) {
        super(api);
    }

    @Override
    public StateValue newValue(Type type) {
        return null;
    }

    @Override
    public StateValue newOperation(AbstractInsnNode insn) throws AnalyzerException {
        return null;
    }

    @Override
    public StateValue copyOperation(AbstractInsnNode insn, StateValue value) throws AnalyzerException {
        return null;
    }

    @Override
    public StateValue unaryOperation(AbstractInsnNode insn, StateValue value) throws AnalyzerException {
        return null;
    }

    @Override
    public StateValue binaryOperation(AbstractInsnNode insn, StateValue value1, StateValue value2) throws AnalyzerException {
        return null;
    }

    @Override
    public StateValue ternaryOperation(AbstractInsnNode insn, StateValue value1, StateValue value2, StateValue value3) throws AnalyzerException {
        return null;
    }

    @Override
    public StateValue naryOperation(AbstractInsnNode insn, List<? extends StateValue> values) throws AnalyzerException {
        return null;
    }

    @Override
    public void returnOperation(AbstractInsnNode insn, StateValue value, StateValue expected) throws AnalyzerException {

    }

    @Override
    public StateValue merge(StateValue value1, StateValue value2) {
        return null;
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/state/StateType.java
================================================
package lsieun.asm.analysis.state;

public enum StateType {
    DEFAULT, // default
    TOP,
    INT,
    FLOAT,
    LONG,
    DOUBLE,
    NULL,

    CP, // constant pool
    HEAP; // 从堆内存上分配的对象
}


================================================
FILE: src/main/java/lsieun/asm/analysis/state/StateValue.java
================================================
package lsieun.asm.analysis.state;

import org.objectweb.asm.tree.analysis.Value;

public class StateValue implements Value {
    public final int size;

    public StateValue(int size) {
        this.size = size;
    }

    @Override
    public int getSize() {
        return size;
    }
}


================================================
FILE: src/main/java/lsieun/asm/analysis/transition/DestinationInterpreter.java
================================================
package lsieun.asm.analysis.transition;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.Interpreter;
import org.objectweb.asm.tree.analysis.SourceValue;

import java.util.HashSet;
import java.util.List;

public class DestinationInterpreter extends Interpreter<SourceValue> implements Opcodes {
    public DestinationInterpreter() {
        super(ASM9);
        if (getClass() != DestinationInterpreter.class) {
            throw new IllegalStateException();
        }
    }

    protected DestinationInterpreter(final int api) {
        super(api);
    }

    @Override
    public SourceValue newValue(Type type) {
        if (type == Type.VOID_TYPE) {
            return null;
        }
        return new SourceValue(type == null ? 1 : type.getSize(), new HashSet<>());
    }

    @Override
    public SourceValue newOperation(AbstractInsnNode insn) {
        int size;
        switch (insn.getOpcode()) {
            case LCONST_0:
            case LCONST_1:
            case DCONST_0:
            case DCONST_1:
                size = 2;
                break;
            case LDC:
                Object value = ((LdcInsnNode) insn).cst;
                size = value instanceof Long || value instanceof Double ? 2 : 1;
                break;
            case GETSTATIC:
                size = Type.getType(((FieldInsnNode) insn).desc).getSize();
                break;
            default:
                size = 1;
                break;
        }
        return new SourceValue(size, new HashSet<>());
    }

    @Override
    public SourceValue copyOperation(AbstractInsnNode insn, SourceValue value) throws AnalyzerException {
        int opcode = insn.getOpcode();
        if (opcode >= ISTORE && opcode <= ASTORE) {
            value.insns.add(insn);
        }

        return new SourceValue(value.getSize(), new HashSet<>());
    }

    @Override
    public SourceValue unaryOperation(AbstractInsnNode insn, SourceValue value) throws AnalyzerException {
        value.insns.add(insn);

        int size;
        switch (insn.getOpcode()) {
            case LNEG:
            case DNEG:
            case I2L:
            case I2D:
            case L2D:
            case F2L:
            case F2D:
            case D2L:
                size = 2;
                break;
            case GETFIELD:
                size = Type.getType(((FieldInsnNode) insn).desc).getSize();
                break;
            default:
                size = 1;
                break;
        }
        return new SourceValue(size, new HashSet<>());
    }

    @Override
    public SourceValue binaryOperation(AbstractInsnNode insn, SourceValue value1, SourceValue value2) throws AnalyzerException {
        value1.insns.add(insn);
        value2.insns.add(insn);

        int size;
        switch (insn.getOpcode()) {
            case LALOAD:
            case DALOAD:
            case LADD:
            case DADD:
            case LSUB:
            case DSUB:
            case LMUL:
            case DMUL:
            case LDIV:
            case DDIV:
            case LREM:
            case DREM:
            case LSHL:
            case LSHR:
            case LUSHR:
            case LAND:
            case LOR:
            case LXOR:
                size = 2;
                break;
            default:
                size = 1;
                break;
        }
        return new SourceValue(size, new HashSet<>());
    }

    @Override
    public SourceValue ternaryOperation(AbstractInsnNode insn, SourceValue value1, SourceValue value2, SourceValue value3) throws AnalyzerException {
        value1.insns.add(insn);
        value2.insns.add(insn);
        value3.insns.add(insn);

        return new SourceValue(1, new HashSet<>());
    }

    @Override
    public SourceValue naryOperation(AbstractInsnNode insn, List<? extends SourceValue> values) throws AnalyzerException {
        if (values != null) {
            for (SourceValue v : values) {
                v.insns.add(insn);
            }
        }

        int size;
        int opcode = insn.getOpcode();
        if (opcode == MULTIANEWARRAY) {
            size = 1;
        }
        else if (opcode == INVOKEDYNAMIC) {
            size = Type.getReturnType(((InvokeDynamicInsnNode) insn).desc).getSize();
        }
        else {
            size = Type.getReturnType(((MethodInsnNode) insn).desc).getSize();
        }
        return new SourceValue(size, new HashSet<>());
    }

    @Override
    public void returnOperation(AbstractInsnNode insn, SourceValue value, SourceValue expected) throws AnalyzerException {
        // Nothing to do.
    }

    @Override
    public SourceValue merge(final SourceValue value1, final SourceValue value2) {
        return new SourceValue(Math.min(value1.size, value2.size), new HashSet<>());
    }
}


================================================
FILE: src/main/java/lsieun/asm/commons/ClassRemapperExample01.java
================================================
package lsieun.asm.commons;

import lsieun.utils.FileUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.commons.SimpleRemapper;

public class ClassRemapperExample01 {
    public static void main(String[] args) {
        String origin_name = "sample/HelloWorld";
        String target_name = "sample/GoodChild";
        String origin_filepath = getFilePath(origin_name);
        byte[] bytes1 = FileUtils.readBytes(origin_filepath);

        //(1)构建ClassReader
        ClassReader cr = new ClassReader(bytes1);

        //(2)构建ClassWriter
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        //(3)串连ClassVisitor
        Remapper remapper = new SimpleRemapper(origin_name, target_name);
        ClassVisitor cv = new ClassRemapper(cw, remapper);

        //(4)两者进行结合
        int parsingOptions = ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
        cr.accept(cv, parsingOptions);

        //(5)重新生成Class
        byte[] bytes2 = cw.toByteArray();

        String target_filepath = getFilePath(target_name);
        FileUtils.writeBytes(target_filepath, bytes2);
    }

    public static String getFilePath(String internalName) {
        String relative_path = String.format("%s.class", internalName);
        return FileUtils.getFilePath(relative_path);
    }
}


================================================
FILE: src/main/java/lsieun/asm/commons/ClassRemapperExample02.java
================================================
package lsieun.asm.commons;

import lsieun.utils.FileUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.commons.SimpleRemapper;

import java.util.HashMap;
import java.util.Map;

public class ClassRemapperExample02 {
    public static void main(String[] args) {
        String origin_name = "sample/HelloWorld";
        String target_name = "sample/GoodChild";
        String origin_filepath = getFilePath(origin_name);
        byte[] bytes1 = FileUtils.readBytes(origin_filepath);

        //(1)构建ClassReader
        ClassReader cr = new ClassReader(bytes1);

        //(2)构建ClassWriter
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        //(3)串连ClassVisitor
        Map<String, String> mapping = new HashMap<>();
        mapping.put(origin_name, target_name);
        mapping.put(origin_name + ".intValue", "a");
        mapping.put(origin_name + ".test()V", "b");
        Remapper mapper = new SimpleRemapper(mapping);
        ClassVisitor cv = new ClassRemapper(cw, mapper);

        //(4)两者进行结合
        int parsingOptions = ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
        cr.accept(cv, parsingOptions);

        //(5)重新生成Class
        byte[] bytes2 = cw.toByteArray();

        String target_filepath = getFilePath(target_name);
        FileUtils.writeBytes(target_filepath, bytes2);
    }

    public static String getFilePath(String internalName) {
        String relative_path = String.format("%s.class", internalName);
        return FileUtils.getFilePath(relative_path);
    }
}


================================================
FILE: src/main/java/lsieun/asm/commons/ClassRemapperExample03.java
================================================
package lsieun.asm.commons;

import lsieun.utils.FileUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.commons.SimpleRemapper;

import java.util.HashMap;
import java.util.Map;

public class ClassRemapperExample03 {
    public static void main(String[] args) {
        Map<String, String> mapping = new HashMap<>();
        mapping.put("sample/HelloWorld", "sample/AAA");
        mapping.put("sample/GoodChild", "sample/BBB");
        mapping.put("sample/HelloWorld.test()V", "a");
        mapping.put("sample/GoodChild.study()V", "b");
        obfuscate("sample/HelloWorld", "sample/AAA", mapping);
        obfuscate("sample/GoodChild", "sample/BBB", mapping);
    }

    public static void obfuscate(String origin_name, String target_name, Map<String, String> mapping) {
        String origin_filepath = getFilePath(origin_name);
        byte[] bytes1 = FileUtils.readBytes(origin_filepath);

        //(1)构建ClassReader
        ClassReader cr = new ClassReader(bytes1);

        //(2)构建ClassWriter
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        //(3)串连ClassVisitor
        Remapper mapper = new SimpleRemapper(mapping);
        ClassVisitor cv = new ClassRemapper(cw, mapper);

        //(4)两者进行结合
        int parsingOptions = ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
        cr.accept(cv, parsingOptions);

        //(5)重新生成Class
        byte[] bytes2 = cw.toByteArray();

        String target_filepath = getFilePath(target_name);
        FileUtils.writeBytes(target_filepath, bytes2);
    }

    public static String getFilePath(String internalName) {
        String relative_path = String.format("%s.class", internalName);
        return FileUtils.getFilePath(relative_path);
    }
}


================================================
FILE: src/main/java/lsieun/asm/commons/GeneratorAdapterExample01.java
================================================
package lsieun.asm.commons;

import lsieun.utils.FileUtils;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;
import org.objectweb.asm.util.TraceClassVisitor;

import java.io.PrintStream;
import java.io.PrintWriter;

import static org.objectweb.asm.Opcodes.*;

public class GeneratorAdapterExample01 {
    public static void main(String[] args) throws Exception {
        String relative_path = "sample/HelloWorld.class";
        String filepath = FileUtils.getFilePath(relative_path);

        // (1) 生成byte[]内容
        byte[] bytes = dump();

        // (2) 保存byte[]到文件
        FileUtils.writeBytes(filepath, bytes);
    }

    public static byte[] dump() throws Exception {
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
        PrintWriter printWriter = new PrintWriter(System.out);
        TraceClassVisitor cv = new TraceClassVisitor(cw, printWriter);

        cv.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "sample/HelloWorld", null, "java/lang/Object", null);

        {
            Method m1 = Method.getMethod("void <init> ()");
            GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m1, null, null, cv);
            mg.loadThis();
            mg.invokeConstructor(Type.getType(Object.class), m1);
            mg.returnValue();
            mg.endMethod();
        }

        {
            Method m2 = Method.getMethod("void main (String[])");
            GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m2, null, null, cv);
            mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
            mg.push("Hello world!");
            mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println (String)"));
            mg.returnValue();
            mg.endMethod();
        }

        cv.visitEnd();

        return cw.toByteArray();
    }
}


================================================
FILE: src/main/java/lsieun/asm/commons/InstructionAdapterExample01.java
================================================
package lsieun.asm.commons;

import lsieun.utils.FileUtils;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;

import static org.objectweb.asm.Opcodes.*;

public class InstructionAdapterExample01 {
    public static void main(String[] args) throws Exception {
        String relative_path = "sample/HelloWorld.class";
        String filepath = FileUtils.getFilePath(relative_path);

        // (1) 生成byte[]内容
        byte[] bytes = dump();

        // (2) 保存byte[]到文件
        FileUtils.writeBytes(filepath, bytes);
    }

    public static byte[] dump() throws Exception {
        // (1) 创建ClassWriter对象
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        // (2) 调用visitXxx()方法
        cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "sample/HelloWorld",
                null, "java/lang/Object", null);

        {
            MethodVisitor mv1 = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            InstructionAdapter ia = new InstructionAdapter(mv1);
            ia.visitCode();
            ia.load(0, InstructionAdapter.OBJECT_TYPE);
            ia.invokespecial("java/lang/Object", "<init>", "()V", false);
            ia.areturn(Type.VOID_TYPE);
            ia.visitMaxs(1, 1);
            ia.visitEnd();
        }

        {
            MethodVisitor mv2 = cw.visitMethod(ACC_PUBLIC, "test", "()V", null, null);
            InstructionAdapter ia = new InstructionAdapter(mv2);
            ia.visitCode();
            ia.getstatic("java/lang/System", "out", "Ljava/io/PrintStream;");
            ia.aconst("Hello World");
            ia.invokevirtual("java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
            ia.areturn(Type.VOID_TYPE);
            ia.visitMaxs(2, 1);
            ia.visitEnd();
        }

        cw.visitEnd();

        // (3) 调用toByteArray()方法
        return cw.toByteArray();
    }
}


================================================
FILE: src/main/java/lsieun/asm/commons/MethodStackMapFrame02Visitor.java
================================================
package lsieun.asm.commons;

import lsieun.classfile.ClassFile;
import lsieun.classfile.InsnRaw;
import org.objectweb.asm.*;
import org.objectweb.asm.commons.AnalyzerAdapter;

import java.util.List;

public class MethodStackMapFrame02Visitor extends ClassVisitor {
    private String owner;
    private final ClassFile classFile;
    private int methodIndex = 0;

    public MethodStackMapFrame02Visitor(int api, ClassVisitor classVisitor, byte[] bytes) {
        super(api, classVisitor);
        this.classFile = new ClassFile(bytes);
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        super.visit(version, access, name, signature, superName, interfaces);
        this.owner = name;
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        byte[] code_bytes = classFile.getCode(methodIndex++);
        InsnRaw insnRaw = new InsnRaw(code_bytes);
        List<String> list = insnRaw.getList();
        mv = new MethodStackMapFrame02Adapter(api, owner, access, name, descriptor, mv, list);
        return mv;
    }

    private static class MethodStackMapFrame02Adapter extends AnalyzerAdapter {
        private static final String FORMAT = "%-30s // %s";
        private static final String START = "{";
        private static final String STOP = "}";
        private static final String EMPTY = "{}";
        private static final String SEPARATOR = "|";

        private final int methodAccess;
        private final String methodName;
        private final String methodDesc;
        private final List<String> insnList;
        private int insnIndex = 0;

        public MethodStackMapFrame02Adapter(int api, String owner, int access, String name, String descriptor, MethodVisitor methodVisitor, List<String> insnList) {
            super(api, owner, access, name, descriptor, methodVisitor);
            this.methodAccess = access;
            this.methodName = name;
            this.methodDesc = descriptor;
            this.insnList = insnList;
        }

        @Override
        public void visitCode() {
            super.visitCode();

            System.out.println(methodName + ":" + methodDesc);
            String frame = getStackFrame();
            String line = String.format(FORMAT, "", frame);
            System.out.println(line);
        }

        @Override
        public void visitFrame(int type, int numLocal, Object[] local, int numStack, Object[] stack) {
            super.visitFrame(type, numLocal, local, numStack, stack);

            String frame = getStackFrame();
            String line = String.format(FORMAT, "", frame);
            System.out.println(line);
        }

        @Override
        public void visitInsn(int opcode) {
            super.visitInsn(opcode);
            printStackMapFrame();
        }

        @Override
        public void visitIntInsn(int opcode, int operand) {
            super.visitIntInsn(opcode, operand);
            printStackMapFrame();
        }

        @Override
        public void visitVarInsn(int opcode, int var) {
            super.visitVarInsn(opcode, var);
            printStackMapFrame();
        }

        @Override
        public void visitTypeInsn(int opcode, String type) {
            super.visitTypeInsn(opcode, type);
            printStackMapFrame();
        }

        @Override
        public void visitFieldInsn(int opcode, String owner, String name, String descriptor) {
            super.visitFieldInsn(opcode, owner, name, descriptor);
            printStackMapFrame();
        }

        @Override
        public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
            super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
            printStackMapFrame();
        }

        @Override
        public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) {
            super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
            printStackMapFrame();
        }

        @Override
        public void visitJumpInsn(int opcode, Label label) {
            super.visitJumpInsn(opcode, label);
            printStackMapFrame();
        }

        @Override
        public void visitLdcInsn(Object value) {
            super.visitLdcInsn(value);
            printStackMapFrame();
        }

        @Override
        public void visitIincInsn(int var, int increment) {
            super.visitIincInsn(var, increment);
            printStackMapFrame();
        }

        @Override
        public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
            super.visitTableSwitchInsn(min, max, dflt, labels);

            int insnSize = insnList.size();
            String insn;
            if (insnIndex < insnSize) {
                insn = insnList.get(insnIndex);
                insnIndex++;
            }
            else {
                insn = "";
            }

            String[] array = insn.split(System.lineSeparator(), 2);
            String frame = getStackFrame();
            String line = String.format(FORMAT, array[0], frame);
            System.out.println(line);
            System.out.println(array[1]);
        }

        @Override
        public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
            super.visitLookupSwitchInsn(dflt, keys, labels);

            int insnSize = insnList.size();
            String insn;
            if (insnIndex < insnSize) {
                insn = insnList.get(insnIndex);
                insnIndex++;
            }
            else {
                insn = "";
            }

            String[] array = insn.split(System.lineSeparator(), 2);
            String frame = getStackFrame();
            String line = String.format(FORMAT, array[0], frame);
            System.out.println(line);
            System.out.println(array[1]);
        }

        @Override
        public void visitMultiANewArrayInsn(String descriptor, int numDimensions) {
            super.visitMultiANewArrayInsn(descriptor, numDimensions);
            printStackMapFrame();
        }

        @Override
        public void visitEnd() {
            super.visitEnd();

            System.out.println();
            System.out.println();
        }

        private void printStackMapFrame() {
            int insnSize = insnList.size();
            String insn;
            if (insnIndex < insnSize) {
                insn = insnList.get(insnIndex);
                insnIndex++;
            }
            else {
                insn = "";
            }

            if (insn.contains(" wide ")) {
                System.out.println(insn);
                insn = insnList.get(insnIndex);
                insnIndex++;
            }

            String frame = getStackFrame();
            String line = String.format(FORMAT, insn, frame);
            System.out.println(line);
        }

        private String getStackFrame() {
            if (locals != null && locals.size() > 0) {
                boolean isStaticMethod = (methodAccess & Opcodes.ACC_STATIC) != 0;
                if (!isStaticMethod) {
                    Object obj = locals.get(0);
                    if (obj != Opcodes.UNINITIALIZED_THIS) {
                        locals.set(0, "this");
                    }
                }
            }
            String locals_str = locals == null ? EMPTY : list2Str(locals);
            String stack_str = stack == null ? EMPTY : list2Str(stack);
            return String.format("%s %s %s", locals_str, SEPARATOR, stack_str);
        }

        private String list2Str(List<Object> list) {
            if (list == null || list.size() == 0) return EMPTY;
            int size = list.size();
            String[] array = new String[size];
            for (int i = 0; i < size; i++) {
                Object item = list.get(i);
                array[i] = item2Str(item);
            }

            return array2Str(array);
        }

        private String array2Str(String[] array) {
            if (array == null || array.length == 0) return EMPTY;
            int length = array.length;

            StringBuilder sb = new StringBuilder();
            sb.append(START);
            for (int i = 0; i < length - 1; i++) {
                sb.append(array[i]).append(", ");
            }
            sb.append(array[length - 1]);
            sb.append(STOP);
            return sb.toString();
        }

        private String item2Str(Object obj) {
            if (obj == Opcodes.TOP) {
                return "top";
            }
            else if (obj == Opcodes.INTEGER) {
                return "int";
            }
            else if (obj == Opcodes.FLOAT) {
                return "float";
            }
            else if (obj == Opcodes.DOUBLE) {
                return "double";
            }
            else if (obj == Opcodes.LONG) {
                return "long";
            }
            else if (obj == Opcodes.NULL) {
                return "null";
            }
            else if (obj == Opcodes.UNINITIALIZED_THIS) {
                return "uninitialized_this";
            }
            else if (obj instanceof Label) {
                Object value = uninitializedTypes.get(obj);
                return "uninitialized_" + getSimpleClassName(value);
            }
            else {
                return getSimpleClassName(obj);
            }
        }

        private String getSimpleClassName(Object obj) {
            if (obj == null) return "null";
            String descriptor = obj.toString();

            int squareIndex = descriptor.lastIndexOf("[");
            String prefix = descriptor.substring(0, squareIndex + 1);

            String simpleName = descriptor.substring(squareIndex + 1);
            if (simpleName.startsWith("L") && simpleName.endsWith(";")) {
                simpleName = simpleName.substring(1, simpleName.length() - 1);
            }

            int slashIndex = simpleName.lastIndexOf("/");
            simpleName = simpleName.substring(slashIndex + 1);

            return prefix + simpleName;
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/commons/MethodStackMapFrameVisitor.java
================================================
package lsieun.asm.commons;

import org.objectweb.asm.*;
import org.objectweb.asm.commons.AnalyzerAdapter;

import java.util.Arrays;
import java.util.List;

public class MethodStackMapFrameVisitor extends ClassVisitor {
    private String owner;

    public MethodStackMapFrameVisitor(int api, ClassVisitor classVisitor) {
        super(api, classVisitor);
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        super.visit(version, access, name, signature, superName, interfaces);
        this.owner = name;
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        return new MethodStackMapFrameAdapter(api, owner, access, name, descriptor, mv);
    }

    private static class MethodStackMapFrameAdapter extends AnalyzerAdapter {
        private final String methodName;
        private final String methodDesc;

        public MethodStackMapFrameAdapter(int api, String owner, int access, String name, String descriptor, MethodVisitor methodVisitor) {
            super(api, owner, access, name, descriptor, methodVisitor);
            this.methodName = name;
            this.methodDesc = descriptor;
        }

        @Override
        public void visitCode() {
            super.visitCode();
            System.out.println();
            System.out.println(methodName + methodDesc);
            printStackMapFrame();
        }

        @Override
        public void visitInsn(int opcode) {
            super.visitInsn(opcode);
            printStackMapFrame();
        }

        @Override
        public void visitIntInsn(int opcode, int operand) {
            super.visitIntInsn(opcode, operand);
            printStackMapFrame();
        }

        @Override
        public void visitVarInsn(int opcode, int var) {
            super.visitVarInsn(opcode, var);
            printStackMapFrame();
        }

        @Override
        public void visitTypeInsn(int opcode, String type) {
            super.visitTypeInsn(opcode, type);
            printStackMapFrame();
        }

        @Override
        public void visitFieldInsn(int opcode, String owner, String name, String descriptor) {
            super.visitFieldInsn(opcode, owner, name, descriptor);
            printStackMapFrame();
        }

        @Override
        public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
            super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
            printStackMapFrame();
        }

        @Override
        public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) {
            super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
            printStackMapFrame();
        }

        @Override
        public void visitJumpInsn(int opcode, Label label) {
            super.visitJumpInsn(opcode, label);
            printStackMapFrame();
        }

        @Override
        public void visitLdcInsn(Object value) {
            super.visitLdcInsn(value);
            printStackMapFrame();
        }

        @Override
        public void visitIincInsn(int var, int increment) {
            super.visitIincInsn(var, increment);
            printStackMapFrame();
        }

        @Override
        public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
            super.visitTableSwitchInsn(min, max, dflt, labels);
            printStackMapFrame();
        }

        @Override
        public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
            super.visitLookupSwitchInsn(dflt, keys, labels);
            printStackMapFrame();
        }

        @Override
        public void visitMultiANewArrayInsn(String descriptor, int numDimensions) {
            super.visitMultiANewArrayInsn(descriptor, numDimensions);
            printStackMapFrame();
        }

        private void printStackMapFrame() {
            String locals_str = locals == null ? "[]" : list2Str(locals);
            String stack_str = stack == null ? "[]" : list2Str(stack);
            String line = String.format("%s %s", locals_str, stack_str);
            System.out.println(line);
        }

        private String list2Str(List<Object> list) {
            if (list == null || list.size() == 0) return "[]";
            int size = list.size();
            String[] array = new String[size];
            for (int i = 0; i < size; i++) {
                Object item = list.get(i);
                array[i] = item2Str(item);
            }
            return Arrays.toString(array);
        }

        private String item2Str(Object obj) {
            if (obj == Opcodes.TOP) {
                return "top";
            }
            else if (obj == Opcodes.INTEGER) {
                return "int";
            }
            else if (obj == Opcodes.FLOAT) {
                return "float";
            }
            else if (obj == Opcodes.DOUBLE) {
                return "double";
            }
            else if (obj == Opcodes.LONG) {
                return "long";
            }
            else if (obj == Opcodes.NULL) {
                return "null";
            }
            else if (obj == Opcodes.UNINITIALIZED_THIS) {
                return "uninitialized_this";
            }
            else if (obj instanceof Label) {
                Object value = uninitializedTypes.get(obj);
                if (value == null) {
                    return obj.toString();
                }
                else {
                    return "uninitialized_" + value;
                }
            }
            else {
                return obj.toString();
            }
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/commons/SerialVersionUIDAdderExample01.java
================================================
package lsieun.asm.commons;

import lsieun.utils.FileUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.SerialVersionUIDAdder;

public class SerialVersionUIDAdderExample01 {
    public static void main(String[] args) {
        String relative_path = "sample/HelloWorld.class";
        String filepath = FileUtils.getFilePath(relative_path);
        byte[] bytes1 = FileUtils.readBytes(filepath);

        //(1)构建ClassReader
        ClassReader cr = new ClassReader(bytes1);

        //(2)构建ClassWriter
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        //(3)串连ClassVisitor
        int api = Opcodes.ASM9;
        ClassVisitor cv = new SerialVersionUIDAdder(cw);

        //(4)结合ClassReader和ClassVisitor
        int parsingOptions = ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
        cr.accept(cv, parsingOptions);

        //(5)生成byte[]
        byte[] bytes2 = cw.toByteArray();

        FileUtils.writeBytes(filepath, bytes2);
    }
}


================================================
FILE: src/main/java/lsieun/asm/commons/StaticInitMergerExample01.java
================================================
package lsieun.asm.commons;

import lsieun.asm.template.ClassAddInterfaceVisitor;
import lsieun.asm.template.ClassMergeVisitor;
import lsieun.utils.FileUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.*;
import org.objectweb.asm.tree.ClassNode;

import java.util.List;

public class StaticInitMergerExample01 {
    private static final int API_VERSION = Opcodes.ASM9;

    public static void main(String[] args) {
        // 第一步,读取两个类文件
        String first_class = "sample/HelloWorld";
        String second_class = "sample/GoodChild";

        String first_class_filepath = getFilePath(first_class);
        byte[] bytes1 = FileUtils.readBytes(first_class_filepath);

        String second_class_filepath = getFilePath(second_class);
        byte[] bytes2 = FileUtils.readBytes(second_class_filepath);

        // 第二步,将sample/GoodChild类重命名为sample/HelloWorld
        byte[] bytes3 = renameClass(second_class, first_class, bytes2);

        // 第三步,合并两个类
        byte[] bytes4 = mergeClass(bytes1, bytes3);

        // 第四步,处理重复的class initialization method
        byte[] bytes5 = removeDuplicateStaticInitMethod(bytes4);
        FileUtils.writeBytes(first_class_filepath, bytes5);
    }

    public static String getFilePath(String internalName) {
        String relative_path = String.format("%s.class", internalName);
        return FileUtils.getFilePath(relative_path);
    }

    public static byte[] renameClass(String origin_name, String target_name, byte[] bytes) {
        //(1)构建ClassReader
        ClassReader cr = new ClassReader(bytes);

        //(2)构建ClassWriter
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        //(3)串连ClassVisitor
        Remapper remapper = new SimpleRemapper(origin_name, target_name);
        ClassVisitor cv = new ClassRemapper(cw, remapper);

        //(4)两者进行结合
        int parsingOptions = ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
        cr.accept(cv, parsingOptions);

        //(5)重新生成Class
        return cw.toByteArray();
    }

    public static byte[] mergeClass(byte[] bytes1, byte[] bytes2) {
        //(1)构建ClassReader
        ClassReader cr = new ClassReader(bytes1);

        //(2)构建ClassWriter
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        //(3)串连ClassVisitor
        ClassNode cn = getClassNode(bytes2);
        List<String> interface_list = cn.interfaces;
        int size = interface_list.size();
        String[] interfaces = new String[size];
        for (int i = 0; i < size; i++) {
            String item = interface_list.get(i);
            interfaces[i] = item;
        }
        ClassMergeVisitor cmv = new ClassMergeVisitor(API_VERSION, cw, cn);
        ClassAddInterfaceVisitor cv = new ClassAddInterfaceVisitor(API_VERSION, cmv, interfaces);

        //(4)两者进行结合
        int parsingOptions = ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
        cr.accept(cv, parsingOptions);

        //(5)重新生成Class
        return cw.toByteArray();
    }

    public static ClassNode getClassNode(byte[] bytes) {
        ClassReader cr = new ClassReader(bytes);
        ClassNode cn = new ClassNode();
        int parsingOptions = ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
        cr.accept(cn, parsingOptions);
        return cn;
    }

    public static byte[] removeDuplicateStaticInitMethod(byte[] bytes) {
        //(1)构建ClassReader
        ClassReader cr = new ClassReader(bytes);

        //(2)构建ClassWriter
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        //(3)串连ClassVisitor
        ClassVisitor cv = new StaticInitMerger("class_init$", cw);

        //(4)结合ClassReader和ClassVisitor
        int parsingOptions = ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES;
        cr.accept(cv, parsingOptions);

        //(5)生成byte[]
        return cw.toByteArray();
    }
}


================================================
FILE: src/main/java/lsieun/asm/core/ChangeURLVisitor.java
================================================
package lsieun.asm.core;

import lsieun.annotation.todo.ToDo;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.AdviceAdapter;

@ToDo("Remove")
public class ChangeURLVisitor extends ClassVisitor {
    public ChangeURLVisitor(ClassVisitor classVisitor) {
        super(Opcodes.ASM9, classVisitor);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        if (mv != null && "<init>".equals(name) && "(Ljava/net/URL;Ljava/lang/String;Ljava/net/URLStreamHandler;)V".equals(descriptor)) {
            mv = new ChangeURLAdapter(mv, access, name, descriptor);
        }
        return mv;
    }

    public class ChangeURLAdapter extends AdviceAdapter {
        protected ChangeURLAdapter(MethodVisitor methodVisitor, int access, String name, String descriptor) {
            super(Opcodes.ASM9, methodVisitor, access, name, descriptor);
        }

        @Override
        protected void onMethodEnter() {
            super.visitVarInsn(ALOAD, 2);
            Label elseLabel = new Label();
            super.visitJumpInsn(IFNULL, elseLabel);
            super.visitVarInsn(ALOAD, 2);
            super.visitLdcInsn("/lservice/rpc/validateKey.action");
            super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "contains", "(Ljava/lang/CharSequence;)Z", false);
            super.visitJumpInsn(IFEQ, elseLabel);
            super.visitTypeInsn(NEW, "java/net/MalformedURLException");
            super.visitInsn(DUP);
            super.visitMethodInsn(INVOKESPECIAL, "java/net/MalformedURLException", "<init>", "()V", false);
            super.visitInsn(ATHROW);
            super.visitLabel(elseLabel);
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/core/ClassChangeVersionVisitor.java
================================================
package lsieun.asm.core;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;

public class ClassChangeVersionVisitor extends ClassVisitor {
    public ClassChangeVersionVisitor(int api, ClassVisitor classVisitor) {
        super(api, classVisitor);
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        super.visit(Opcodes.V1_7, access, name, signature, superName, interfaces);
    }
}


================================================
FILE: src/main/java/lsieun/asm/core/ClassCloneVisitor.java
================================================
package lsieun.asm.core;

import org.objectweb.asm.ClassVisitor;

public class ClassCloneVisitor extends ClassVisitor {
    public ClassCloneVisitor(int api, ClassVisitor cw) {
        super(api, cw);
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        super.visit(version, access, name, signature, superName, new String[]{"java/lang/Cloneable"});
    }
}


================================================
FILE: src/main/java/lsieun/asm/core/ClassDecompileVisitor.java
================================================
package lsieun.asm.core;

import org.objectweb.asm.*;

public class ClassDecompileVisitor extends ClassVisitor {

    public ClassDecompileVisitor() {
        super(Opcodes.ASM9);
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        System.out.println(name + " extends " + superName + " {");
    }

    @Override
    public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
        System.out.println("    " + descriptor + " " + name);
        return null;
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        System.out.println("    " + name + " " + descriptor);
        return null;
    }

    @Override
    public void visitEnd() {
        System.out.println("}");
    }
}


================================================
FILE: src/main/java/lsieun/asm/core/ClassListMemberVisitor.java
================================================
package lsieun.asm.core;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;

import java.util.Arrays;
import java.util.Formatter;

public class ClassListMemberVisitor extends ClassVisitor {
    private final Formatter fm = new Formatter();

    public ClassListMemberVisitor(int api) {
        super(api);
    }

    public ClassListMemberVisitor(int api, ClassVisitor classVisitor) {
        super(api, classVisitor);
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        fm.format("%s extends %s implements %s {%n", name, superName, Arrays.toString(interfaces));
    }

    @Override
    public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
        fm.format("    %s: %s%n", name, descriptor);
        return null;
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        fm.format("    %s: %s%n", name, descriptor);
        return null;
    }

    @Override
    public void visitEnd() {
        fm.format("}");
    }

    public String getText() {
        return fm.toString();
    }
}


================================================
FILE: src/main/java/lsieun/asm/core/ClassRemoveAttributeVisitor.java
================================================
package lsieun.asm.core;

import org.objectweb.asm.ClassVisitor;

public class ClassRemoveAttributeVisitor extends ClassVisitor {
    public ClassRemoveAttributeVisitor(int api, ClassVisitor cv) {
        super(api, cv);
    }

    @Override
    public void visitSource(String source, String debug) {
        // do nothing
    }

    @Override
    public void visitOuterClass(String owner, String name, String descriptor) {
        // do nothing
    }

    @Override
    public void visitInnerClass(String name, String outerName, String innerName, int access) {
        // do nothing
    }
}


================================================
FILE: src/main/java/lsieun/asm/core/MethodAroundVisitor.java
================================================
package lsieun.asm.core;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import static org.objectweb.asm.Opcodes.*;

public class MethodAroundVisitor extends ClassVisitor {
    public MethodAroundVisitor(int api, ClassVisitor classVisitor) {
        super(api, classVisitor);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        if (mv != null && !"<init>".equals(name)) {
            boolean isAbstractMethod = (access & Opcodes.ACC_ABSTRACT) == Opcodes.ACC_ABSTRACT;
            boolean isNativeMethod = (access & Opcodes.ACC_NATIVE) == Opcodes.ACC_NATIVE;
            if (!isAbstractMethod && !isNativeMethod) {
                mv = new MethodAroundAdapter(api, mv);
            }
        }
        return mv;
    }

    private static class MethodAroundAdapter extends MethodVisitor {
        public MethodAroundAdapter(int api, MethodVisitor methodVisitor) {
            super(api, methodVisitor);
        }

        @Override
        public void visitCode() {
            // 首先,处理自己的代码逻辑
            super.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
            super.visitLdcInsn("Method Enter...");
            super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);

            // 其次,调用父类的方法实现
            super.visitCode();
        }

        @Override
        public void visitInsn(int opcode) {
            // 首先,处理自己的代码逻辑
            if (opcode == ATHROW || (opcode >= IRETURN && opcode <= RETURN)) {
                super.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
                super.visitLdcInsn("Method Exit...");
                super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
            }

            // 其次,调用父类的方法实现
            super.visitInsn(opcode);
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/core/MethodAroundVisitor2.java
================================================
package lsieun.asm.core;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import static org.objectweb.asm.Opcodes.*;

public class MethodAroundVisitor2 extends ClassVisitor {
    public MethodAroundVisitor2(int api, ClassVisitor classVisitor) {
        super(api, classVisitor);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        if (mv != null && !"<init>".equals(name)) {
            boolean isAbstractMethod = (access & Opcodes.ACC_ABSTRACT) == Opcodes.ACC_ABSTRACT;
            boolean isNativeMethod = (access & Opcodes.ACC_NATIVE) == Opcodes.ACC_NATIVE;
            if (!isAbstractMethod && !isNativeMethod) {
                mv = new MethodAroundAdapter(api, mv);
            }
        }
        return mv;
    }

    private static class MethodAroundAdapter extends MethodVisitor {
        public MethodAroundAdapter(int api, MethodVisitor methodVisitor) {
            super(api, methodVisitor);
        }

        @Override
        public void visitCode() {
            // 首先,处理自己的代码逻辑
            super.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
            super.visitLdcInsn("Method Enter222");
            super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);

            // 其次,调用父类的方法实现
            super.visitCode();
        }

        @Override
        public void visitInsn(int opcode) {
            // 首先,处理自己的代码逻辑
            if (opcode == ATHROW || (opcode >= IRETURN && opcode <= RETURN)) {
                super.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
                super.visitLdcInsn("Method Exit222");
                super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
            }

            // 其次,调用父类的方法实现
            super.visitInsn(opcode);
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/core/MethodEmptyBodyVisitor.java
================================================
package lsieun.asm.core;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import static org.objectweb.asm.Opcodes.*;

public class MethodEmptyBodyVisitor extends ClassVisitor {
    private String owner;
    private final String methodName;
    private final String methodDesc;

    public MethodEmptyBodyVisitor(int api, ClassVisitor classVisitor, String methodName, String methodDesc) {
        super(api, classVisitor);
        this.methodName = methodName;
        this.methodDesc = methodDesc;
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        super.visit(version, access, name, signature, superName, interfaces);
        this.owner = name;
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        if (mv != null && methodName.equals(name) && methodDesc.equals(descriptor)) {
            boolean isAbstractMethod = (access & ACC_ABSTRACT) != 0;
            boolean isNativeMethod = (access & ACC_NATIVE) != 0;
            if (!isAbstractMethod && !isNativeMethod) {
                generateNewBody(mv, owner, access, name, descriptor);
                return null;
            }
        }
        return mv;
    }

    protected void generateNewBody(MethodVisitor mv, String owner, int methodAccess, String methodName, String methodDesc) {
        // (1) method argument types and return type
        Type t = Type.getType(methodDesc);
        Type[] argumentTypes = t.getArgumentTypes();
        Type returnType = t.getReturnType();


        // (2) compute the size of local variable and operand stack
        boolean isStaticMethod = ((methodAccess & Opcodes.ACC_STATIC) != 0);
        int localSize = isStaticMethod ? 0 : 1;
        for (Type argType : argumentTypes) {
            localSize += argType.getSize();
        }
        int stackSize = returnType.getSize();


        // (3) method body
        mv.visitCode();
        if (returnType.getSort() == Type.VOID) {
            mv.visitInsn(RETURN);
        }
        else if (returnType.getSort() >= Type.BOOLEAN && returnType.getSort() <= Type.INT) {
            mv.visitInsn(ICONST_1);
            mv.visitInsn(IRETURN);
        }
        else if (returnType.getSort() == Type.LONG) {
            mv.visitInsn(LCONST_0);
            mv.visitInsn(LRETURN);
        }
        else if (returnType.getSort() == Type.FLOAT) {
            mv.visitInsn(FCONST_0);
            mv.visitInsn(FRETURN);
        }
        else if (returnType.getSort() == Type.DOUBLE) {
            mv.visitInsn(DCONST_0);
            mv.visitInsn(DRETURN);
        }
        else {
            mv.visitInsn(ACONST_NULL);
            mv.visitInsn(ARETURN);
        }
        mv.visitMaxs(stackSize, localSize);
        mv.visitEnd();
    }
}


================================================
FILE: src/main/java/lsieun/asm/core/MethodEnterVisitor.java
================================================
package lsieun.asm.core;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import static org.objectweb.asm.Opcodes.*;

public class MethodEnterVisitor extends ClassVisitor {
    public MethodEnterVisitor(int api, ClassVisitor classVisitor) {
        super(api, classVisitor);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        if (mv != null && !"<init>".equals(name)) {
            mv = new MethodEnterAdapter(api, mv);
        }
        return mv;
    }

    private static class MethodEnterAdapter extends MethodVisitor {
        public MethodEnterAdapter(int api, MethodVisitor methodVisitor) {
            super(api, methodVisitor);
        }

        @Override
        public void visitCode() {
            // 首先,处理自己的代码逻辑
            super.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
            super.visitLdcInsn("Method Enter...");
            super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);

            // 其次,调用父类的方法实现
            super.visitCode();
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/core/MethodExitVisitor.java
================================================
package lsieun.asm.core;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class MethodExitVisitor extends ClassVisitor {
    public MethodExitVisitor(int api, ClassVisitor classVisitor) {
        super(api, classVisitor);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        if (mv != null && !"<init>".equals(name)) {
            mv = new MethodExitAdapter(api, mv);
        }
        return mv;
    }

    private static class MethodExitAdapter extends MethodVisitor {
        public MethodExitAdapter(int api, MethodVisitor methodVisitor) {
            super(api, methodVisitor);
        }

        @Override
        public void visitInsn(int opcode) {
            // 首先,处理自己的代码逻辑
            if (opcode == Opcodes.ATHROW || (opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)) {
                super.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
                super.visitLdcInsn("Method Exit...");
                super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
            }

            // 其次,调用父类的方法实现
            super.visitInsn(opcode);
        }
    }
}


================================================
FILE: src/main/java/lsieun/asm/core/MethodFindInvokeVisitor.java
================================================
package lsieun.asm.core;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.util.Printer;

import java.util.ArrayList;
import java.util.List;

public class MethodFindInvokeVisitor extends ClassVisitor {
    private final String methodName;
    private fina
Download .txt
gitextract_4n4clgmd/

├── .gitignore
├── LICENSE
├── README.md
├── accepted-words.dic
├── pom.xml
└── src/
    └── main/
        └── java/
            ├── lsieun/
            │   ├── annotation/
            │   │   └── todo/
            │   │       └── ToDo.java
            │   ├── asm/
            │   │   ├── analysis/
            │   │   │   ├── ControlFlowAnalyzer.java
            │   │   │   ├── ControlFlowAnalyzer2.java
            │   │   │   ├── ControlFlowEdgeAnalyzer.java
            │   │   │   ├── ControlFlowEdgeAnalyzer2.java
            │   │   │   ├── ControlFlowGraphAnalyzer.java
            │   │   │   ├── DataFlowAnalyzer.java
            │   │   │   ├── InsnText.java
            │   │   │   ├── MockAnalyzer.java
            │   │   │   ├── RemoveDeadCodeNode.java
            │   │   │   ├── RemoveDeadCodeVisitor.java
            │   │   │   ├── RemoveUnusedCastNode.java
            │   │   │   ├── RemoveUnusedCastVisitor.java
            │   │   │   ├── cc/
            │   │   │   │   ├── CyclomaticComplexity.java
            │   │   │   │   ├── CyclomaticComplexityAnalyzer.java
            │   │   │   │   └── CyclomaticComplexityFrame.java
            │   │   │   ├── cfg/
            │   │   │   │   ├── ControlFlowBuilder.java
            │   │   │   │   ├── ControlFlowGraph.java
            │   │   │   │   ├── Edge.java
            │   │   │   │   ├── EdgeCreator.java
            │   │   │   │   ├── FramelessAnalyzer.java
            │   │   │   │   └── SimpleEdgeCreator.java
            │   │   │   ├── diagnosis/
            │   │   │   │   ├── DeadCodeDiagnosis.java
            │   │   │   │   ├── NullDereferenceDiagnosis.java
            │   │   │   │   ├── NullabilityDiagnosis.java
            │   │   │   │   ├── RedundantVariableDiagnosis.java
            │   │   │   │   ├── RelatedInstructionDiagnosis.java
            │   │   │   │   └── ReverseEngineerMethodArgumentsDiagnosis.java
            │   │   │   ├── graph/
            │   │   │   │   ├── InsnBlock.java
            │   │   │   │   ├── TextBox.java
            │   │   │   │   └── TextGraph.java
            │   │   │   ├── nullability/
            │   │   │   │   ├── NullDeferenceInterpreter.java
            │   │   │   │   ├── Nullability.java
            │   │   │   │   ├── NullabilityAnalyzer.java
            │   │   │   │   ├── NullabilityFrame.java
            │   │   │   │   ├── NullabilityInterpreter.java
            │   │   │   │   └── NullabilityValue.java
            │   │   │   ├── state/
            │   │   │   │   ├── StateInterpreter.java
            │   │   │   │   ├── StateType.java
            │   │   │   │   └── StateValue.java
            │   │   │   └── transition/
            │   │   │       └── DestinationInterpreter.java
            │   │   ├── commons/
            │   │   │   ├── ClassRemapperExample01.java
            │   │   │   ├── ClassRemapperExample02.java
            │   │   │   ├── ClassRemapperExample03.java
            │   │   │   ├── GeneratorAdapterExample01.java
            │   │   │   ├── InstructionAdapterExample01.java
            │   │   │   ├── MethodStackMapFrame02Visitor.java
            │   │   │   ├── MethodStackMapFrameVisitor.java
            │   │   │   ├── SerialVersionUIDAdderExample01.java
            │   │   │   └── StaticInitMergerExample01.java
            │   │   ├── core/
            │   │   │   ├── ChangeURLVisitor.java
            │   │   │   ├── ClassChangeVersionVisitor.java
            │   │   │   ├── ClassCloneVisitor.java
            │   │   │   ├── ClassDecompileVisitor.java
            │   │   │   ├── ClassListMemberVisitor.java
            │   │   │   ├── ClassRemoveAttributeVisitor.java
            │   │   │   ├── MethodAroundVisitor.java
            │   │   │   ├── MethodAroundVisitor2.java
            │   │   │   ├── MethodEmptyBodyVisitor.java
            │   │   │   ├── MethodEnterVisitor.java
            │   │   │   ├── MethodExitVisitor.java
            │   │   │   ├── MethodFindInvokeVisitor.java
            │   │   │   ├── MethodFindRefVisitor.java
            │   │   │   ├── MethodParameterVisitor.java
            │   │   │   ├── MethodParameterVisitor2.java
            │   │   │   ├── MethodPatternAdapter.java
            │   │   │   ├── MethodRemoveAddZeroVisitor.java
            │   │   │   ├── MethodRemoveGetFieldPutFieldVisitor.java
            │   │   │   ├── MethodRemoveNopVisitor.java
            │   │   │   ├── MethodRemovePrintVisitor.java
            │   │   │   ├── MethodReplaceInvokeVisitor.java
            │   │   │   ├── MethodTimerVisitor.java
            │   │   │   ├── MethodTimerVisitor2.java
            │   │   │   ├── MethodTimerVisitor3.java
            │   │   │   ├── MethodTimerVisitor4.java
            │   │   │   ├── SuperPackageAttribute.java
            │   │   │   ├── counter/
            │   │   │   │   ├── ClassCounterVisitor.java
            │   │   │   │   └── MethodCounterAdapter.java
            │   │   │   ├── empty/
            │   │   │   │   ├── EmptyAnnotationVisitor.java
            │   │   │   │   ├── EmptyClassVisitor.java
            │   │   │   │   ├── EmptyFieldVisitor.java
            │   │   │   │   ├── EmptyMethodVisitor.java
            │   │   │   │   ├── EmptyModuleVisitor.java
            │   │   │   │   └── EmptyRecordComponentVisitor.java
            │   │   │   ├── info/
            │   │   │   │   ├── InfoClassVisitor.java
            │   │   │   │   ├── InfoFieldVisitor.java
            │   │   │   │   └── InfoMethodVisitor.java
            │   │   │   └── timer/
            │   │   │       ├── ClassTimerVisitor.java
            │   │   │       └── MethodTimerAdapter.java
            │   │   ├── template/
            │   │   │   ├── CheckMethodAnnotationVisitor.java
            │   │   │   ├── ClassAddAnnotationVisitor.java
            │   │   │   ├── ClassAddCustomAttributeVisitor.java
            │   │   │   ├── ClassAddFieldVisitor.java
            │   │   │   ├── ClassAddInterfaceVisitor.java
            │   │   │   ├── ClassAddMethodVisitor.java
            │   │   │   ├── ClassGetAttributeContentVisitor.java
            │   │   │   ├── ClassMergeVisitor.java
            │   │   │   ├── ClassMergeVisitorRun.java
            │   │   │   ├── ClassPrintAnnotationVisitor.java
            │   │   │   ├── ClassPrintParameterVisitor.java
            │   │   │   ├── ClassRemoveFieldVisitor.java
            │   │   │   ├── ClassRemoveMethodVisitor.java
            │   │   │   ├── ClassRenameAdapter.java
            │   │   │   ├── ClassRenameAdapterRun.java
            │   │   │   ├── ClassReplaceMethodBodyVisitor.java
            │   │   │   ├── CustomAttribute.java
            │   │   │   ├── FieldAccessAdapter.java
            │   │   │   ├── FieldAccessAdapterRun.java
            │   │   │   ├── FieldAccessConverter.java
            │   │   │   ├── Info.java
            │   │   │   ├── MethodCallAdapter.java
            │   │   │   ├── MethodCallAdapterRun.java
            │   │   │   ├── MethodCallConverter.java
            │   │   │   ├── MethodEnteringAdapter.java
            │   │   │   ├── MethodEnteringVisitor.java
            │   │   │   ├── MethodEnteringVisitorRun.java
            │   │   │   ├── MethodExitingAdapter.java
            │   │   │   ├── MethodExitingAdapterRun.java
            │   │   │   ├── MethodExitingConverter.java
            │   │   │   ├── MethodFinallyAdapter.java
            │   │   │   ├── MethodFinallyAdapterRun.java
            │   │   │   ├── MethodFinallyConverter.java
            │   │   │   ├── MethodPrintInstructionAdapter.java
            │   │   │   ├── MethodPrintInstructionVisitor.java
            │   │   │   ├── MethodWithSameTryCatchLogicVisitor.java
            │   │   │   ├── MethodWithWholeTryCatchVisitor.java
            │   │   │   ├── RefRenameAdapter.java
            │   │   │   └── RemoveSyntheticVisitor.java
            │   │   ├── tree/
            │   │   │   ├── ChangeMemberNameBasedOnAnnotationNode.java
            │   │   │   ├── ChangeThisNode.java
            │   │   │   ├── ClassAddCustomAttributeNode.java
            │   │   │   ├── ClassAddFieldNode.java
            │   │   │   ├── ClassAddMethodNode.java
            │   │   │   ├── ClassAddTimerNode.java
            │   │   │   ├── ClassRemoveFieldNode.java
            │   │   │   ├── ClassRemoveMethodNode.java
            │   │   │   ├── MixCore2TreeVisitor.java
            │   │   │   ├── MixTree2CoreNode.java
            │   │   │   ├── OptimizeJumpNode.java
            │   │   │   ├── RemoveGetFieldPutFieldNode.java
            │   │   │   ├── my/
            │   │   │   │   ├── MyClassNode.java
            │   │   │   │   ├── MyClassVisitor.java
            │   │   │   │   ├── MyMethodAdapter.java
            │   │   │   │   └── MyMethodNode.java
            │   │   │   └── transformer/
            │   │   │       ├── ClassTransformer.java
            │   │   │       └── MethodTransformer.java
            │   │   └── util/
            │   │       ├── CheckClassAdapterExample01Generate.java
            │   │       ├── CheckClassAdapterExample02Generate.java
            │   │       ├── CodeUtils.java
            │   │       ├── TraceClassVisitorExample01Generate.java
            │   │       ├── TraceClassVisitorExample02Transform.java
            │   │       ├── TraceClassVisitorExample03.java
            │   │       └── TreePrinter.java
            │   ├── classfile/
            │   │   ├── CPInfo.java
            │   │   ├── ClassFile.java
            │   │   └── InsnRaw.java
            │   ├── cst/
            │   │   └── Const.java
            │   ├── drawing/
            │   │   ├── canvas/
            │   │   │   ├── Box.java
            │   │   │   ├── Canvas.java
            │   │   │   ├── Drawable.java
            │   │   │   ├── TextAlign.java
            │   │   │   ├── TextDirection.java
            │   │   │   └── TextPixel.java
            │   │   └── theme/
            │   │       ├── line/
            │   │       │   └── ContinuousLine.java
            │   │       ├── shape/
            │   │       │   ├── Rectangle.java
            │   │       │   └── RectangleWithText.java
            │   │       ├── table/
            │   │       │   ├── AbstractTable.java
            │   │       │   ├── FixedWidthOneLineTable.java
            │   │       │   └── OneLineTable.java
            │   │       └── text/
            │   │           └── PlainText.java
            │   ├── trove/
            │   │   ├── HashFunctions.java
            │   │   ├── PrimeFinder.java
            │   │   ├── THash.java
            │   │   ├── TIntArrayList.java
            │   │   ├── TIntFunction.java
            │   │   ├── TIntHash.java
            │   │   ├── TIntHashingStrategy.java
            │   │   ├── TIntIntHashMap.java
            │   │   ├── TIntIntIterator.java
            │   │   ├── TIntIntProcedure.java
            │   │   ├── TIntProcedure.java
            │   │   ├── TIterator.java
            │   │   ├── TPrimitiveHash.java
            │   │   ├── TPrimitiveIterator.java
            │   │   └── package-info.java
            │   └── utils/
            │       ├── ASMUtilsCore.java
            │       ├── ASMUtilsTree.java
            │       ├── BoxDrawingUtils.java
            │       ├── ByteArrayClassLoader.java
            │       ├── ByteUtils.java
            │       ├── DescriptorUtils.java
            │       ├── FileUtils.java
            │       ├── FrameUtils.java
            │       ├── HexFormat.java
            │       ├── HexUtils.java
            │       ├── IOUtils.java
            │       ├── JarUtils.java
            │       ├── OpcodeConst.java
            │       ├── ReadUtils.java
            │       ├── StringUtils.java
            │       └── ValueUtils.java
            ├── run/
            │   ├── ASMPrint.java
            │   ├── BoxDrawingRun.java
            │   ├── BytecodeRun.java
            │   ├── ControlFlowGraphRun.java
            │   ├── ControlFlowGraphType.java
            │   ├── HelloWorldAnalysisCore.java
            │   ├── HelloWorldAnalysisTree.java
            │   ├── HelloWorldFrameCore.java
            │   ├── HelloWorldFrameCore02.java
            │   ├── HelloWorldFrameTree.java
            │   ├── HelloWorldGenerateCore.java
            │   ├── HelloWorldGenerateTree.java
            │   ├── HelloWorldRun.java
            │   ├── HelloWorldTransformCore.java
            │   ├── HelloWorldTransformTree.java
            │   ├── MockAnalyzerRun.java
            │   ├── PrintASMCodeCore.java
            │   ├── PrintASMCodeTree.java
            │   ├── PrintASMTextClass.java
            │   ├── PrintASMTextLambda.java
            │   ├── PrintOpcodeTable.java
            │   └── jar/
            │       ├── CompareTwoJarFile.java
            │       └── FindJarClassItem.java
            └── sample/
                ├── HelloWorld.java
                └── ParameterUtils.java
Download .txt
SYMBOL INDEX (1337 symbols across 224 files)

FILE: src/main/java/lsieun/asm/analysis/ControlFlowAnalyzer.java
  class ControlFlowAnalyzer (line 18) | public class ControlFlowAnalyzer implements Opcodes {
    method ControlFlowAnalyzer (line 40) | public ControlFlowAnalyzer() {
    method getHandlers (line 43) | public List<TryCatchBlockNode> getHandlers(final int insnIndex) {
    method analyze (line 48) | @SuppressWarnings("unchecked")
    method init (line 142) | protected void init(final String owner, final MethodNode method) throw...
    method initInstructionsToProcess (line 147) | private void initInstructionsToProcess() {
    method removeInstructionsToProcess (line 154) | private int removeInstructionsToProcess() {
    method addInstructionsToProcess (line 161) | private void addInstructionsToProcess(final int insnIndex) {
    method newControlFlowEdge (line 168) | protected void newControlFlowEdge(final int insnIndex, final int succe...
    method newControlFlowExceptionEdge (line 173) | protected void newControlFlowExceptionEdge(final int insnIndex, final ...
    method newControlFlowExceptionEdge (line 177) | protected void newControlFlowExceptionEdge(final int insnIndex, final ...

FILE: src/main/java/lsieun/asm/analysis/ControlFlowAnalyzer2.java
  class ControlFlowAnalyzer2 (line 10) | public class ControlFlowAnalyzer2 extends ControlFlowAnalyzer{
    method ControlFlowAnalyzer2 (line 14) | public ControlFlowAnalyzer2() {
    method analyze (line 18) | @Override
    method newControlFlowEdge (line 34) | @Override
    method addNext (line 70) | private void addNext(int fromIndex, int toIndex) {
    method addJump (line 76) | private void addJump(int fromIndex, int toIndex) {
    method removeNextAndJump (line 82) | private void removeNextAndJump(int insnIndex) {
    method getBlock (line 88) | private InsnBlock getBlock(int insnIndex) {
    method getBlocks (line 97) | public InsnBlock[] getBlocks() {

FILE: src/main/java/lsieun/asm/analysis/ControlFlowEdgeAnalyzer.java
  class ControlFlowEdgeAnalyzer (line 10) | public class ControlFlowEdgeAnalyzer<V extends Value> extends Analyzer<V> {
    method ControlFlowEdgeAnalyzer (line 14) | public ControlFlowEdgeAnalyzer(Interpreter<V> interpreter) {
    method analyze (line 18) | @Override
    method newControlFlowEdge (line 34) | @Override
    method addNext (line 70) | private void addNext(int fromIndex, int toIndex) {
    method addJump (line 76) | private void addJump(int fromIndex, int toIndex) {
    method removeNextAndJump (line 82) | private void removeNextAndJump(int insnIndex) {
    method getBlock (line 88) | private InsnBlock getBlock(int insnIndex) {
    method getBlocks (line 97) | public InsnBlock[] getBlocks() {

FILE: src/main/java/lsieun/asm/analysis/ControlFlowEdgeAnalyzer2.java
  class ControlFlowEdgeAnalyzer2 (line 12) | public class ControlFlowEdgeAnalyzer2<V extends Value> extends ControlFl...
    method ControlFlowEdgeAnalyzer2 (line 14) | public ControlFlowEdgeAnalyzer2(Interpreter<V> interpreter) {
    method getBlocks (line 18) | @Override

FILE: src/main/java/lsieun/asm/analysis/ControlFlowGraphAnalyzer.java
  class ControlFlowGraphAnalyzer (line 10) | public class ControlFlowGraphAnalyzer {
    method ControlFlowGraphAnalyzer (line 20) | public ControlFlowGraphAnalyzer() {
    method analyze (line 24) | public void analyze(MethodNode mn) {
    method findJumpLabel (line 31) | private void findJumpLabel(MethodNode mn) {
    method instruction2Block (line 60) | private void instruction2Block(MethodNode mn) {
    method linkBlocks (line 164) | private void linkBlocks() {
    method addJumpFromBlockToLabel (line 177) | private void addJumpFromBlockToLabel(LabelNode labelNode) {
    method completeBlock (line 190) | private void completeBlock() {
    method getBlocks (line 200) | public InsnBlock[] getBlocks() {

FILE: src/main/java/lsieun/asm/analysis/DataFlowAnalyzer.java
  class DataFlowAnalyzer (line 14) | public class DataFlowAnalyzer<V extends Value> implements Opcodes {
    method DataFlowAnalyzer (line 31) | public DataFlowAnalyzer(final Interpreter<V> interpreter) {
    method getHandlers (line 35) | public List<TryCatchBlockNode> getHandlers(final int insnIndex) {
    method getFrames (line 39) | public Frame<V>[] getFrames() {
    method analyze (line 44) | @SuppressWarnings("unchecked")
    method computeInitialFrame (line 179) | private Frame<V> computeInitialFrame(final String owner, final MethodN...
    method init (line 208) | protected void init(final String owner, final MethodNode method) throw...
    method newFrame (line 212) | protected Frame<V> newFrame(final int numLocals, final int numStack) {
    method newFrame (line 216) | protected Frame<V> newFrame(final Frame<? extends V> frame) {
    method newControlFlowEdge (line 220) | protected void newControlFlowEdge(final int insnIndex, final int succe...
    method newControlFlowExceptionEdge (line 224) | protected boolean newControlFlowExceptionEdge(final int insnIndex, fin...
    method newControlFlowExceptionEdge (line 228) | protected boolean newControlFlowExceptionEdge(final int insnIndex, fin...
    method merge (line 234) | private void merge(final int insnIndex, final Frame<V> frame)

FILE: src/main/java/lsieun/asm/analysis/InsnText.java
  class InsnText (line 15) | public class InsnText {
    method toLines (line 20) | public List<String> toLines(AbstractInsnNode[] array) {
    method toLines (line 33) | public List<String> toLines(AbstractInsnNode node) {
    method node_to_str (line 53) | public String node_to_str(AbstractInsnNode currentNode) {
    method table_switch_node_to_str_list (line 202) | public List<String> table_switch_node_to_str_list(TableSwitchInsnNode ...
    method lookup_switch_node_to_str_list (line 219) | public List<String> lookup_switch_node_to_str_list(LookupSwitchInsnNod...
    method getLabelName (line 237) | private String getLabelName(LabelNode labelNode) {
    method getOpcodeName (line 246) | private static String getOpcodeName(AbstractInsnNode currentNode) {
    method getSimpleName (line 251) | private static String getSimpleName(String descriptor) {

FILE: src/main/java/lsieun/asm/analysis/MockAnalyzer.java
  class MockAnalyzer (line 11) | public class MockAnalyzer<V extends Value> implements Opcodes {
    method MockAnalyzer (line 14) | public MockAnalyzer(Interpreter<V> interpreter) {
    method analyze (line 18) | @SuppressWarnings("unchecked")
    method getCount (line 116) | private int getCount(boolean[] array) {
    method getFirst (line 126) | private int getFirst(boolean[] array) {
    method computeInitialFrame (line 137) | private Frame<V> computeInitialFrame(final String owner, final MethodN...
    method merge (line 182) | private void merge(Frame<V>[] frames, int insnIndex, Frame<V> newFrame...

FILE: src/main/java/lsieun/asm/analysis/RemoveDeadCodeNode.java
  class RemoveDeadCodeNode (line 11) | public class RemoveDeadCodeNode extends ClassNode {
    method RemoveDeadCodeNode (line 12) | public RemoveDeadCodeNode(int api, ClassVisitor cv) {
    method visitEnd (line 17) | @Override
    class MethodRemoveDeadCodeTransformer (line 34) | private static class MethodRemoveDeadCodeTransformer extends MethodTra...
      method MethodRemoveDeadCodeTransformer (line 37) | public MethodRemoveDeadCodeTransformer(String owner, MethodTransform...
      method transform (line 42) | @Override

FILE: src/main/java/lsieun/asm/analysis/RemoveDeadCodeVisitor.java
  class RemoveDeadCodeVisitor (line 10) | public class RemoveDeadCodeVisitor extends ClassVisitor {
    method RemoveDeadCodeVisitor (line 13) | public RemoveDeadCodeVisitor(int api, ClassVisitor cv) {
    method visit (line 17) | @Override
    method visitMethod (line 23) | @Override
    class MethodRemoveDeadCodeAdapter (line 32) | private static class MethodRemoveDeadCodeAdapter extends MethodVisitor {
      method MethodRemoveDeadCodeAdapter (line 36) | public MethodRemoveDeadCodeAdapter(int api, String owner, int access...
      method visitEnd (line 42) | @Override

FILE: src/main/java/lsieun/asm/analysis/RemoveUnusedCastNode.java
  class RemoveUnusedCastNode (line 11) | public class RemoveUnusedCastNode extends ClassNode {
    method RemoveUnusedCastNode (line 12) | public RemoveUnusedCastNode(int api, ClassVisitor cv) {
    method visitEnd (line 17) | @Override
    class MethodRemoveUnusedCastTransformer (line 41) | private static class MethodRemoveUnusedCastTransformer extends MethodT...
      method MethodRemoveUnusedCastTransformer (line 44) | public MethodRemoveUnusedCastTransformer(String owner, MethodTransfo...
      method transform (line 49) | @Override
      method getClass (line 79) | private static Class<?> getClass(String desc) {
      method getClass (line 88) | private static Class<?> getClass(Type t) {

FILE: src/main/java/lsieun/asm/analysis/RemoveUnusedCastVisitor.java
  class RemoveUnusedCastVisitor (line 9) | public class RemoveUnusedCastVisitor extends ClassVisitor {
    method RemoveUnusedCastVisitor (line 12) | public RemoveUnusedCastVisitor(int api, ClassVisitor classVisitor) {
    method visit (line 16) | @Override
    method visitMethod (line 22) | @Override
    class RemoveUnusedCastAdapter (line 38) | private static class RemoveUnusedCastAdapter extends MethodVisitor {
      method RemoveUnusedCastAdapter (line 41) | public RemoveUnusedCastAdapter(int api, MethodVisitor methodVisitor) {
      method visitTypeInsn (line 45) | @Override
      method getClass (line 65) | private static Class<?> getClass(String desc) {

FILE: src/main/java/lsieun/asm/analysis/cc/CyclomaticComplexity.java
  class CyclomaticComplexity (line 6) | public class CyclomaticComplexity {
    method getCyclomaticComplexity (line 7) | public static int getCyclomaticComplexity(String owner, MethodNode mn)...

FILE: src/main/java/lsieun/asm/analysis/cc/CyclomaticComplexityAnalyzer.java
  class CyclomaticComplexityAnalyzer (line 5) | public class CyclomaticComplexityAnalyzer<V extends Value> extends Analy...
    method CyclomaticComplexityAnalyzer (line 6) | public CyclomaticComplexityAnalyzer(Interpreter<V> interpreter) {
    method newFrame (line 10) | @Override
    method newFrame (line 15) | @Override
    method newControlFlowEdge (line 20) | @Override

FILE: src/main/java/lsieun/asm/analysis/cc/CyclomaticComplexityFrame.java
  class CyclomaticComplexityFrame (line 9) | public class CyclomaticComplexityFrame<V extends Value> extends Frame<V> {
    method CyclomaticComplexityFrame (line 12) | public CyclomaticComplexityFrame(int numLocals, int numStack) {
    method CyclomaticComplexityFrame (line 16) | public CyclomaticComplexityFrame(Frame<? extends V> frame) {

FILE: src/main/java/lsieun/asm/analysis/cfg/ControlFlowBuilder.java
  class ControlFlowBuilder (line 9) | public final class ControlFlowBuilder {
    method buildCFG (line 10) | public static ControlFlowGraph buildCFG(String className, MethodNode m...

FILE: src/main/java/lsieun/asm/analysis/cfg/ControlFlowGraph.java
  class ControlFlowGraph (line 6) | public final class ControlFlowGraph {
    method ControlFlowGraph (line 10) | public ControlFlowGraph(int[][] transitions, int[][] errorTransitions) {
    method toString (line 15) | @Override

FILE: src/main/java/lsieun/asm/analysis/cfg/Edge.java
  class Edge (line 3) | public final class Edge {
    method Edge (line 7) | public Edge(int from, int to) {
    method equals (line 12) | @Override
    method hashCode (line 22) | @Override

FILE: src/main/java/lsieun/asm/analysis/cfg/EdgeCreator.java
  type EdgeCreator (line 3) | public interface EdgeCreator {
    method newControlFlowEdge (line 4) | void newControlFlowEdge(int insn, int successor);
    method newControlFlowExceptionEdge (line 6) | void newControlFlowExceptionEdge(int insn, int successor, boolean npe);

FILE: src/main/java/lsieun/asm/analysis/cfg/FramelessAnalyzer.java
  class FramelessAnalyzer (line 18) | public class FramelessAnalyzer {
    method FramelessAnalyzer (line 34) | public FramelessAnalyzer(EdgeCreator creator) {
    method analyze (line 38) | public void analyze(MethodNode m) throws AnalyzerException {
    method merge (line 150) | protected void merge(int insn) {
    method newListArray (line 164) | public static <V> List<V>[] newListArray(int size) {

FILE: src/main/java/lsieun/asm/analysis/cfg/SimpleEdgeCreator.java
  class SimpleEdgeCreator (line 5) | public class SimpleEdgeCreator implements EdgeCreator {
    method SimpleEdgeCreator (line 9) | public SimpleEdgeCreator(int size) {
    method newControlFlowEdge (line 18) | @Override
    method newControlFlowExceptionEdge (line 25) | @Override

FILE: src/main/java/lsieun/asm/analysis/diagnosis/DeadCodeDiagnosis.java
  class DeadCodeDiagnosis (line 9) | public class DeadCodeDiagnosis {
    method diagnose (line 10) | public static int[] diagnose(String className, MethodNode mn) throws A...

FILE: src/main/java/lsieun/asm/analysis/diagnosis/NullDereferenceDiagnosis.java
  class NullDereferenceDiagnosis (line 16) | public class NullDereferenceDiagnosis {
    method diagnose (line 17) | public static int[] diagnose(String owner, MethodNode mn) throws Analy...
    method getTarget (line 42) | private static BasicValue getTarget(AbstractInsnNode insn, Frame<Basic...
    method getStackValue (line 62) | private static BasicValue getStackValue(Frame<BasicValue> frame, int i...

FILE: src/main/java/lsieun/asm/analysis/diagnosis/NullabilityDiagnosis.java
  class NullabilityDiagnosis (line 22) | public class NullabilityDiagnosis {
    method diagnose (line 23) | public static int[] diagnose(String className, MethodNode mn) throws A...
    method getTarget (line 49) | private static NullabilityValue getTarget(AbstractInsnNode insn, Frame...
    method getStackValue (line 69) | private static NullabilityValue getStackValue(Frame<NullabilityValue> ...

FILE: src/main/java/lsieun/asm/analysis/diagnosis/RedundantVariableDiagnosis.java
  class RedundantVariableDiagnosis (line 13) | public class RedundantVariableDiagnosis {
    method diagnose (line 14) | public static int[] diagnose(String className, MethodNode mn) throws A...

FILE: src/main/java/lsieun/asm/analysis/diagnosis/RelatedInstructionDiagnosis.java
  class RelatedInstructionDiagnosis (line 16) | public class RelatedInstructionDiagnosis {
    method diagnose (line 17) | public static int[] diagnose(String className, MethodNode mn, int insn...
    method getSourceFrames (line 78) | private static Frame<SourceValue>[] getSourceFrames(String className, ...
    method getDestinationFrames (line 83) | private static Frame<SourceValue>[] getDestinationFrames(String classN...

FILE: src/main/java/lsieun/asm/analysis/diagnosis/ReverseEngineerMethodArgumentsDiagnosis.java
  class ReverseEngineerMethodArgumentsDiagnosis (line 10) | public class ReverseEngineerMethodArgumentsDiagnosis {
    method diagnose (line 13) | public static void diagnose(String className, MethodNode mn) throws An...
    method getMethodVariableName (line 55) | public static String getMethodVariableName(AbstractInsnNode insn, List...
    method findMethodInvokes (line 71) | public static int[] findMethodInvokes(InsnList instructions) {

FILE: src/main/java/lsieun/asm/analysis/graph/InsnBlock.java
  class InsnBlock (line 6) | public class InsnBlock {
    method addLines (line 14) | public void addLines(List<String> list) {
    method addNext (line 18) | public void addNext(InsnBlock item) {
    method addJump (line 24) | public void addJump(InsnBlock item) {

FILE: src/main/java/lsieun/asm/analysis/graph/TextBox.java
  class TextBox (line 3) | public class TextBox {
    method TextBox (line 9) | public TextBox(int row, int col, int width, int height) {
    method valueOf (line 16) | public static TextBox valueOf(int row, int col, int width, int height) {

FILE: src/main/java/lsieun/asm/analysis/graph/TextGraph.java
  class TextGraph (line 12) | public class TextGraph {
    method TextGraph (line 22) | public TextGraph(InsnBlock[] blockArray) {
    method draw (line 29) | @SuppressWarnings("UnnecessaryLocalVariable")
    method drawBoxAndText (line 52) | private void drawBoxAndText(TextBox box, List<String> lines) {
    method drawLinks (line 63) | private void drawLinks() {
    method findBoxes (line 116) | private List<TextBox> findBoxes(List<InsnBlock> blockList) {
    method getOdd (line 129) | private int getOdd(int num) {
    method findMaxStringLength (line 137) | private int findMaxStringLength(InsnBlock[] blockArray) {
    method findMaxStringLength (line 148) | private int findMaxStringLength(List<String> lines) {

FILE: src/main/java/lsieun/asm/analysis/nullability/NullDeferenceInterpreter.java
  class NullDeferenceInterpreter (line 10) | public class NullDeferenceInterpreter extends BasicInterpreter {
    method NullDeferenceInterpreter (line 14) | public NullDeferenceInterpreter(int api) {
    method newOperation (line 18) | @Override
    method merge (line 26) | @Override
    method isRef (line 34) | private boolean isRef(Value value) {

FILE: src/main/java/lsieun/asm/analysis/nullability/Nullability.java
  type Nullability (line 3) | public enum Nullability {
    method Nullability (line 11) | Nullability(int priority) {
    method merge (line 15) | public static Nullability merge(Nullability value1, Nullability value2) {

FILE: src/main/java/lsieun/asm/analysis/nullability/NullabilityAnalyzer.java
  class NullabilityAnalyzer (line 7) | public class NullabilityAnalyzer extends Analyzer<NullabilityValue> {
    method NullabilityAnalyzer (line 8) | public NullabilityAnalyzer(Interpreter<NullabilityValue> interpreter) {
    method newFrame (line 12) | @Override
    method newFrame (line 17) | @Override

FILE: src/main/java/lsieun/asm/analysis/nullability/NullabilityFrame.java
  class NullabilityFrame (line 7) | public class NullabilityFrame extends Frame<NullabilityValue> {
    method NullabilityFrame (line 8) | public NullabilityFrame(int numLocals, int numStack) {
    method NullabilityFrame (line 12) | public NullabilityFrame(NullabilityFrame frame) {
    method initJumpTarget (line 16) | @Override
    method updateFrame (line 46) | private void updateFrame(NullabilityValue oldValue, Nullability newSta...

FILE: src/main/java/lsieun/asm/analysis/nullability/NullabilityInterpreter.java
  class NullabilityInterpreter (line 13) | public class NullabilityInterpreter extends Interpreter<NullabilityValue...
    method NullabilityInterpreter (line 21) | public NullabilityInterpreter(int api) {
    method newValue (line 25) | @Override
    method newOperation (line 38) | @Override
    method copyOperation (line 112) | @Override
    method unaryOperation (line 117) | @Override
    method binaryOperation (line 199) | @Override
    method ternaryOperation (line 269) | @Override
    method naryOperation (line 277) | @Override
    method returnOperation (line 292) | @Override
    method merge (line 299) | @Override
    method isInterface (line 362) | protected boolean isInterface(final Type type) {
    method getSuperClass (line 366) | protected Type getSuperClass(final Type type) {
    method newArrayValue (line 371) | private NullabilityValue newArrayValue(final Type type, final int dime...
    method getElementValue (line 385) | protected NullabilityValue getElementValue(final NullabilityValue obje...
    method isSubTypeOf (line 398) | protected boolean isSubTypeOf(final NullabilityValue value, final Null...
    method isAssignableFrom (line 435) | protected boolean isAssignableFrom(final Type type1, final Type type2) {
    method getClass (line 442) | protected Class<?> getClass(final Type type) {

FILE: src/main/java/lsieun/asm/analysis/nullability/NullabilityValue.java
  class NullabilityValue (line 6) | public class NullabilityValue implements Value {
    method NullabilityValue (line 10) | public NullabilityValue(Type type) {
    method NullabilityValue (line 14) | public NullabilityValue(Type type, Nullability state) {
    method getType (line 19) | public Type getType() {
    method setState (line 23) | public void setState(Nullability state) {
    method getState (line 27) | public Nullability getState() {
    method getSize (line 31) | @Override
    method isReference (line 36) | public boolean isReference() {
    method equals (line 40) | @Override
    method hashCode (line 59) | @Override

FILE: src/main/java/lsieun/asm/analysis/state/StateInterpreter.java
  class StateInterpreter (line 11) | public class StateInterpreter extends Interpreter<StateValue> implements...
    method StateInterpreter (line 12) | public StateInterpreter() {
    method StateInterpreter (line 19) | public StateInterpreter(int api) {
    method newValue (line 23) | @Override
    method newOperation (line 28) | @Override
    method copyOperation (line 33) | @Override
    method unaryOperation (line 38) | @Override
    method binaryOperation (line 43) | @Override
    method ternaryOperation (line 48) | @Override
    method naryOperation (line 53) | @Override
    method returnOperation (line 58) | @Override
    method merge (line 63) | @Override

FILE: src/main/java/lsieun/asm/analysis/state/StateType.java
  type StateType (line 3) | public enum StateType {

FILE: src/main/java/lsieun/asm/analysis/state/StateValue.java
  class StateValue (line 5) | public class StateValue implements Value {
    method StateValue (line 8) | public StateValue(int size) {
    method getSize (line 12) | @Override

FILE: src/main/java/lsieun/asm/analysis/transition/DestinationInterpreter.java
  class DestinationInterpreter (line 13) | public class DestinationInterpreter extends Interpreter<SourceValue> imp...
    method DestinationInterpreter (line 14) | public DestinationInterpreter() {
    method DestinationInterpreter (line 21) | protected DestinationInterpreter(final int api) {
    method newValue (line 25) | @Override
    method newOperation (line 33) | @Override
    method copyOperation (line 57) | @Override
    method unaryOperation (line 67) | @Override
    method binaryOperation (line 93) | @Override
    method ternaryOperation (line 127) | @Override
    method naryOperation (line 136) | @Override
    method returnOperation (line 158) | @Override
    method merge (line 163) | @Override

FILE: src/main/java/lsieun/asm/commons/ClassRemapperExample01.java
  class ClassRemapperExample01 (line 11) | public class ClassRemapperExample01 {
    method main (line 12) | public static void main(String[] args) {
    method getFilePath (line 39) | public static String getFilePath(String internalName) {

FILE: src/main/java/lsieun/asm/commons/ClassRemapperExample02.java
  class ClassRemapperExample02 (line 14) | public class ClassRemapperExample02 {
    method main (line 15) | public static void main(String[] args) {
    method getFilePath (line 46) | public static String getFilePath(String internalName) {

FILE: src/main/java/lsieun/asm/commons/ClassRemapperExample03.java
  class ClassRemapperExample03 (line 14) | public class ClassRemapperExample03 {
    method main (line 15) | public static void main(String[] args) {
    method obfuscate (line 25) | public static void obfuscate(String origin_name, String target_name, M...
    method getFilePath (line 50) | public static String getFilePath(String internalName) {

FILE: src/main/java/lsieun/asm/commons/GeneratorAdapterExample01.java
  class GeneratorAdapterExample01 (line 15) | public class GeneratorAdapterExample01 {
    method main (line 16) | public static void main(String[] args) throws Exception {
    method dump (line 27) | public static byte[] dump() throws Exception {

FILE: src/main/java/lsieun/asm/commons/InstructionAdapterExample01.java
  class InstructionAdapterExample01 (line 11) | public class InstructionAdapterExample01 {
    method main (line 12) | public static void main(String[] args) throws Exception {
    method dump (line 23) | public static byte[] dump() throws Exception {

FILE: src/main/java/lsieun/asm/commons/MethodStackMapFrame02Visitor.java
  class MethodStackMapFrame02Visitor (line 10) | public class MethodStackMapFrame02Visitor extends ClassVisitor {
    method MethodStackMapFrame02Visitor (line 15) | public MethodStackMapFrame02Visitor(int api, ClassVisitor classVisitor...
    method visit (line 20) | @Override
    method visitMethod (line 26) | @Override
    class MethodStackMapFrame02Adapter (line 36) | private static class MethodStackMapFrame02Adapter extends AnalyzerAdap...
      method MethodStackMapFrame02Adapter (line 49) | public MethodStackMapFrame02Adapter(int api, String owner, int acces...
      method visitCode (line 57) | @Override
      method visitFrame (line 67) | @Override
      method visitInsn (line 76) | @Override
      method visitIntInsn (line 82) | @Override
      method visitVarInsn (line 88) | @Override
      method visitTypeInsn (line 94) | @Override
      method visitFieldInsn (line 100) | @Override
      method visitMethodInsn (line 106) | @Override
      method visitInvokeDynamicInsn (line 112) | @Override
      method visitJumpInsn (line 118) | @Override
      method visitLdcInsn (line 124) | @Override
      method visitIincInsn (line 130) | @Override
      method visitTableSwitchInsn (line 136) | @Override
      method visitLookupSwitchInsn (line 157) | @Override
      method visitMultiANewArrayInsn (line 178) | @Override
      method visitEnd (line 184) | @Override
      method printStackMapFrame (line 192) | private void printStackMapFrame() {
      method getStackFrame (line 214) | private String getStackFrame() {
      method list2Str (line 229) | private String list2Str(List<Object> list) {
      method array2Str (line 241) | private String array2Str(String[] array) {
      method item2Str (line 255) | private String item2Str(Object obj) {
      method getSimpleClassName (line 286) | private String getSimpleClassName(Object obj) {

FILE: src/main/java/lsieun/asm/commons/MethodStackMapFrameVisitor.java
  class MethodStackMapFrameVisitor (line 9) | public class MethodStackMapFrameVisitor extends ClassVisitor {
    method MethodStackMapFrameVisitor (line 12) | public MethodStackMapFrameVisitor(int api, ClassVisitor classVisitor) {
    method visit (line 16) | @Override
    method visitMethod (line 22) | @Override
    class MethodStackMapFrameAdapter (line 28) | private static class MethodStackMapFrameAdapter extends AnalyzerAdapter {
      method MethodStackMapFrameAdapter (line 32) | public MethodStackMapFrameAdapter(int api, String owner, int access,...
      method visitCode (line 38) | @Override
      method visitInsn (line 46) | @Override
      method visitIntInsn (line 52) | @Override
      method visitVarInsn (line 58) | @Override
      method visitTypeInsn (line 64) | @Override
      method visitFieldInsn (line 70) | @Override
      method visitMethodInsn (line 76) | @Override
      method visitInvokeDynamicInsn (line 82) | @Override
      method visitJumpInsn (line 88) | @Override
      method visitLdcInsn (line 94) | @Override
      method visitIincInsn (line 100) | @Override
      method visitTableSwitchInsn (line 106) | @Override
      method visitLookupSwitchInsn (line 112) | @Override
      method visitMultiANewArrayInsn (line 118) | @Override
      method printStackMapFrame (line 124) | private void printStackMapFrame() {
      method list2Str (line 131) | private String list2Str(List<Object> list) {
      method item2Str (line 142) | private String item2Str(Object obj) {

FILE: src/main/java/lsieun/asm/commons/SerialVersionUIDAdderExample01.java
  class SerialVersionUIDAdderExample01 (line 10) | public class SerialVersionUIDAdderExample01 {
    method main (line 11) | public static void main(String[] args) {

FILE: src/main/java/lsieun/asm/commons/StaticInitMergerExample01.java
  class StaticInitMergerExample01 (line 15) | public class StaticInitMergerExample01 {
    method main (line 18) | public static void main(String[] args) {
    method getFilePath (line 40) | public static String getFilePath(String internalName) {
    method renameClass (line 45) | public static byte[] renameClass(String origin_name, String target_nam...
    method mergeClass (line 64) | public static byte[] mergeClass(byte[] bytes1, byte[] bytes2) {
    method getClassNode (line 91) | public static ClassNode getClassNode(byte[] bytes) {
    method removeDuplicateStaticInitMethod (line 99) | public static byte[] removeDuplicateStaticInitMethod(byte[] bytes) {

FILE: src/main/java/lsieun/asm/core/ChangeURLVisitor.java
  class ChangeURLVisitor (line 10) | @ToDo("Remove")
    method ChangeURLVisitor (line 12) | public ChangeURLVisitor(ClassVisitor classVisitor) {
    method visitMethod (line 16) | @Override
    class ChangeURLAdapter (line 25) | public class ChangeURLAdapter extends AdviceAdapter {
      method ChangeURLAdapter (line 26) | protected ChangeURLAdapter(MethodVisitor methodVisitor, int access, ...
      method onMethodEnter (line 30) | @Override

FILE: src/main/java/lsieun/asm/core/ClassChangeVersionVisitor.java
  class ClassChangeVersionVisitor (line 6) | public class ClassChangeVersionVisitor extends ClassVisitor {
    method ClassChangeVersionVisitor (line 7) | public ClassChangeVersionVisitor(int api, ClassVisitor classVisitor) {
    method visit (line 11) | @Override

FILE: src/main/java/lsieun/asm/core/ClassCloneVisitor.java
  class ClassCloneVisitor (line 5) | public class ClassCloneVisitor extends ClassVisitor {
    method ClassCloneVisitor (line 6) | public ClassCloneVisitor(int api, ClassVisitor cw) {
    method visit (line 10) | @Override

FILE: src/main/java/lsieun/asm/core/ClassDecompileVisitor.java
  class ClassDecompileVisitor (line 5) | public class ClassDecompileVisitor extends ClassVisitor {
    method ClassDecompileVisitor (line 7) | public ClassDecompileVisitor() {
    method visit (line 11) | @Override
    method visitField (line 16) | @Override
    method visitMethod (line 22) | @Override
    method visitEnd (line 28) | @Override

FILE: src/main/java/lsieun/asm/core/ClassListMemberVisitor.java
  class ClassListMemberVisitor (line 10) | public class ClassListMemberVisitor extends ClassVisitor {
    method ClassListMemberVisitor (line 13) | public ClassListMemberVisitor(int api) {
    method ClassListMemberVisitor (line 17) | public ClassListMemberVisitor(int api, ClassVisitor classVisitor) {
    method visit (line 21) | @Override
    method visitField (line 26) | @Override
    method visitMethod (line 32) | @Override
    method visitEnd (line 38) | @Override
    method getText (line 43) | public String getText() {

FILE: src/main/java/lsieun/asm/core/ClassRemoveAttributeVisitor.java
  class ClassRemoveAttributeVisitor (line 5) | public class ClassRemoveAttributeVisitor extends ClassVisitor {
    method ClassRemoveAttributeVisitor (line 6) | public ClassRemoveAttributeVisitor(int api, ClassVisitor cv) {
    method visitSource (line 10) | @Override
    method visitOuterClass (line 15) | @Override
    method visitInnerClass (line 20) | @Override

FILE: src/main/java/lsieun/asm/core/MethodAroundVisitor.java
  class MethodAroundVisitor (line 9) | public class MethodAroundVisitor extends ClassVisitor {
    method MethodAroundVisitor (line 10) | public MethodAroundVisitor(int api, ClassVisitor classVisitor) {
    method visitMethod (line 14) | @Override
    class MethodAroundAdapter (line 27) | private static class MethodAroundAdapter extends MethodVisitor {
      method MethodAroundAdapter (line 28) | public MethodAroundAdapter(int api, MethodVisitor methodVisitor) {
      method visitCode (line 32) | @Override
      method visitInsn (line 43) | @Override

FILE: src/main/java/lsieun/asm/core/MethodAroundVisitor2.java
  class MethodAroundVisitor2 (line 9) | public class MethodAroundVisitor2 extends ClassVisitor {
    method MethodAroundVisitor2 (line 10) | public MethodAroundVisitor2(int api, ClassVisitor classVisitor) {
    method visitMethod (line 14) | @Override
    class MethodAroundAdapter (line 27) | private static class MethodAroundAdapter extends MethodVisitor {
      method MethodAroundAdapter (line 28) | public MethodAroundAdapter(int api, MethodVisitor methodVisitor) {
      method visitCode (line 32) | @Override
      method visitInsn (line 43) | @Override

FILE: src/main/java/lsieun/asm/core/MethodEmptyBodyVisitor.java
  class MethodEmptyBodyVisitor (line 10) | public class MethodEmptyBodyVisitor extends ClassVisitor {
    method MethodEmptyBodyVisitor (line 15) | public MethodEmptyBodyVisitor(int api, ClassVisitor classVisitor, Stri...
    method visit (line 21) | @Override
    method visitMethod (line 27) | @Override
    method generateNewBody (line 41) | protected void generateNewBody(MethodVisitor mv, String owner, int met...

FILE: src/main/java/lsieun/asm/core/MethodEnterVisitor.java
  class MethodEnterVisitor (line 10) | public class MethodEnterVisitor extends ClassVisitor {
    method MethodEnterVisitor (line 11) | public MethodEnterVisitor(int api, ClassVisitor classVisitor) {
    method visitMethod (line 15) | @Override
    class MethodEnterAdapter (line 24) | private static class MethodEnterAdapter extends MethodVisitor {
      method MethodEnterAdapter (line 25) | public MethodEnterAdapter(int api, MethodVisitor methodVisitor) {
      method visitCode (line 29) | @Override

FILE: src/main/java/lsieun/asm/core/MethodExitVisitor.java
  class MethodExitVisitor (line 7) | public class MethodExitVisitor extends ClassVisitor {
    method MethodExitVisitor (line 8) | public MethodExitVisitor(int api, ClassVisitor classVisitor) {
    method visitMethod (line 12) | @Override
    class MethodExitAdapter (line 21) | private static class MethodExitAdapter extends MethodVisitor {
      method MethodExitAdapter (line 22) | public MethodExitAdapter(int api, MethodVisitor methodVisitor) {
      method visitInsn (line 26) | @Override

FILE: src/main/java/lsieun/asm/core/MethodFindInvokeVisitor.java
  class MethodFindInvokeVisitor (line 10) | public class MethodFindInvokeVisitor extends ClassVisitor {
    method MethodFindInvokeVisitor (line 14) | public MethodFindInvokeVisitor(int api, ClassVisitor classVisitor, Str...
    method visitMethod (line 20) | @Override
    class MethodFindInvokeAdapter (line 28) | private static class MethodFindInvokeAdapter extends MethodVisitor {
      method MethodFindInvokeAdapter (line 31) | public MethodFindInvokeAdapter(int api, MethodVisitor methodVisitor) {
      method visitMethodInsn (line 35) | @Override
      method visitEnd (line 47) | @Override

FILE: src/main/java/lsieun/asm/core/MethodFindRefVisitor.java
  class MethodFindRefVisitor (line 12) | public class MethodFindRefVisitor extends ClassVisitor {
    method MethodFindRefVisitor (line 20) | public MethodFindRefVisitor(int api, ClassVisitor classVisitor, String...
    method visit (line 27) | @Override
    method visitMethod (line 33) | @Override
    method visitEnd (line 43) | @Override
    class MethodFindRefAdaptor (line 54) | private class MethodFindRefAdaptor extends MethodVisitor {
      method MethodFindRefAdaptor (line 59) | public MethodFindRefAdaptor(int api, MethodVisitor methodVisitor, St...
      method visitMethodInsn (line 66) | @Override

FILE: src/main/java/lsieun/asm/core/MethodParameterVisitor.java
  class MethodParameterVisitor (line 10) | public class MethodParameterVisitor extends ClassVisitor {
    method MethodParameterVisitor (line 11) | public MethodParameterVisitor(int api, ClassVisitor classVisitor) {
    method visitMethod (line 15) | @Override
    class MethodParameterAdapter (line 28) | private static class MethodParameterAdapter extends MethodVisitor {
      method MethodParameterAdapter (line 33) | public MethodParameterAdapter(int api, MethodVisitor mv, int methodA...
      method visitCode (line 40) | @Override
      method visitInsn (line 98) | @Override
      method printBoolean (line 145) | private void printBoolean() {
      method printChar (line 151) | private void printChar() {
      method printInt (line 157) | private void printInt() {
      method printFloat (line 163) | private void printFloat() {
      method printLong (line 169) | private void printLong() {
      method printDouble (line 176) | private void printDouble() {
      method printString (line 183) | private void printString() {
      method printObject (line 189) | private void printObject() {
      method printMessage (line 195) | private void printMessage(String str) {

FILE: src/main/java/lsieun/asm/core/MethodParameterVisitor2.java
  class MethodParameterVisitor2 (line 9) | public class MethodParameterVisitor2 extends ClassVisitor {
    method MethodParameterVisitor2 (line 10) | public MethodParameterVisitor2(int api, ClassVisitor classVisitor) {
    method visitMethod (line 14) | @Override
    class MethodParameterAdapter2 (line 27) | private static class MethodParameterAdapter2 extends MethodVisitor {
      method MethodParameterAdapter2 (line 32) | public MethodParameterAdapter2(int api, MethodVisitor mv, int method...
      method visitCode (line 39) | @Override
      method visitInsn (line 70) | @Override
      method printMessage (line 106) | private void printMessage(String str) {
      method printValueOnStack (line 111) | private void printValueOnStack(String descriptor) {

FILE: src/main/java/lsieun/asm/core/MethodPatternAdapter.java
  class MethodPatternAdapter (line 7) | public abstract class MethodPatternAdapter extends MethodVisitor {
    method MethodPatternAdapter (line 11) | public MethodPatternAdapter(int api, MethodVisitor methodVisitor) {
    method visitInsn (line 15) | @Override
    method visitIntInsn (line 21) | @Override
    method visitVarInsn (line 27) | @Override
    method visitTypeInsn (line 33) | @Override
    method visitFieldInsn (line 39) | @Override
    method visitMethodInsn (line 45) | @Override
    method visitMethodInsn (line 51) | @Override
    method visitInvokeDynamicInsn (line 57) | @Override
    method visitJumpInsn (line 63) | @Override
    method visitLdcInsn (line 69) | @Override
    method visitIincInsn (line 75) | @Override
    method visitTableSwitchInsn (line 81) | @Override
    method visitLookupSwitchInsn (line 87) | @Override
    method visitMultiANewArrayInsn (line 93) | @Override
    method visitTryCatchBlock (line 99) | @Override
    method visitLabel (line 105) | @Override
    method visitFrame (line 111) | @Override
    method visitMaxs (line 117) | @Override
    method visitInsn (line 123) | protected abstract void visitInsn();

FILE: src/main/java/lsieun/asm/core/MethodRemoveAddZeroVisitor.java
  class MethodRemoveAddZeroVisitor (line 8) | public class MethodRemoveAddZeroVisitor extends ClassVisitor {
    method MethodRemoveAddZeroVisitor (line 9) | public MethodRemoveAddZeroVisitor(int api, ClassVisitor classVisitor) {
    method visitMethod (line 13) | @Override
    class MethodRemoveAddZeroAdapter (line 26) | private static class MethodRemoveAddZeroAdapter extends MethodPatternA...
      method MethodRemoveAddZeroAdapter (line 29) | public MethodRemoveAddZeroAdapter(int api, MethodVisitor methodVisit...
      method visitInsn (line 33) | @Override
      method visitInsn (line 59) | @Override

FILE: src/main/java/lsieun/asm/core/MethodRemoveGetFieldPutFieldVisitor.java
  class MethodRemoveGetFieldPutFieldVisitor (line 8) | public class MethodRemoveGetFieldPutFieldVisitor extends ClassVisitor {
    method MethodRemoveGetFieldPutFieldVisitor (line 9) | public MethodRemoveGetFieldPutFieldVisitor(int api, ClassVisitor class...
    method visitMethod (line 13) | @Override
    class MethodRemoveGetFieldPutFieldAdapter (line 26) | private class MethodRemoveGetFieldPutFieldAdapter extends MethodPatter...
      method MethodRemoveGetFieldPutFieldAdapter (line 35) | public MethodRemoveGetFieldPutFieldAdapter(int api, MethodVisitor me...
      method visitVarInsn (line 39) | @Override
      method visitFieldInsn (line 67) | @Override
      method visitInsn (line 92) | @Override

FILE: src/main/java/lsieun/asm/core/MethodRemoveNopVisitor.java
  class MethodRemoveNopVisitor (line 8) | public class MethodRemoveNopVisitor extends ClassVisitor {
    method MethodRemoveNopVisitor (line 9) | public MethodRemoveNopVisitor(int api, ClassVisitor classVisitor) {
    method visitMethod (line 13) | @Override
    class MethodRemoveNopAdapter (line 27) | private static class MethodRemoveNopAdapter extends MethodVisitor {
      method MethodRemoveNopAdapter (line 28) | public MethodRemoveNopAdapter(int api, MethodVisitor methodVisitor) {
      method visitInsn (line 32) | @Override

FILE: src/main/java/lsieun/asm/core/MethodRemovePrintVisitor.java
  class MethodRemovePrintVisitor (line 8) | public class MethodRemovePrintVisitor extends ClassVisitor {
    method MethodRemovePrintVisitor (line 9) | public MethodRemovePrintVisitor(int api, ClassVisitor classVisitor) {
    method visitMethod (line 13) | @Override
    class MethodRemovePrintAdaptor (line 26) | private class MethodRemovePrintAdaptor extends MethodPatternAdapter {
      method MethodRemovePrintAdaptor (line 32) | public MethodRemovePrintAdaptor(int api, MethodVisitor methodVisitor) {
      method visitFieldInsn (line 36) | @Override
      method visitLdcInsn (line 58) | @Override
      method visitMethodInsn (line 75) | @Override
      method visitInsn (line 92) | @Override

FILE: src/main/java/lsieun/asm/core/MethodReplaceInvokeVisitor.java
  class MethodReplaceInvokeVisitor (line 9) | public class MethodReplaceInvokeVisitor extends ClassVisitor {
    method MethodReplaceInvokeVisitor (line 19) | public MethodReplaceInvokeVisitor(int api, ClassVisitor classVisitor,
    method visitMethod (line 33) | @Override
    class MethodReplaceInvokeAdapter (line 46) | private class MethodReplaceInvokeAdapter extends MethodVisitor {
      method MethodReplaceInvokeAdapter (line 47) | public MethodReplaceInvokeAdapter(int api, MethodVisitor methodVisit...
      method visitMethodInsn (line 51) | @Override

FILE: src/main/java/lsieun/asm/core/MethodTimerVisitor.java
  class MethodTimerVisitor (line 9) | public class MethodTimerVisitor extends ClassVisitor {
    method MethodTimerVisitor (line 13) | public MethodTimerVisitor(int api, ClassVisitor classVisitor) {
    method visit (line 17) | @Override
    method visitMethod (line 24) | @Override
    method visitEnd (line 37) | @Override
    class MethodTimerAdapter (line 48) | private static class MethodTimerAdapter extends MethodVisitor {
      method MethodTimerAdapter (line 51) | public MethodTimerAdapter(int api, MethodVisitor mv, String owner) {
      method visitCode (line 56) | @Override
      method visitInsn (line 68) | @Override

FILE: src/main/java/lsieun/asm/core/MethodTimerVisitor2.java
  class MethodTimerVisitor2 (line 9) | public class MethodTimerVisitor2 extends ClassVisitor {
    method MethodTimerVisitor2 (line 13) | public MethodTimerVisitor2(int api, ClassVisitor classVisitor) {
    method visit (line 17) | @Override
    method visitMethod (line 24) | @Override
    method getFieldName (line 45) | private String getFieldName(String methodName) {
    class MethodTimerAdapter2 (line 49) | private class MethodTimerAdapter2 extends MethodVisitor {
      method MethodTimerAdapter2 (line 53) | public MethodTimerAdapter2(int api, MethodVisitor mv, String owner, ...
      method visitCode (line 59) | @Override
      method visitInsn (line 71) | @Override

FILE: src/main/java/lsieun/asm/core/MethodTimerVisitor3.java
  class MethodTimerVisitor3 (line 10) | public class MethodTimerVisitor3 extends ClassVisitor {
    method MethodTimerVisitor3 (line 11) | public MethodTimerVisitor3(int api, ClassVisitor cv) {
    method visitMethod (line 15) | @Override
    class MethodTimerAdapter3 (line 29) | private static class MethodTimerAdapter3 extends LocalVariablesSorter {
      method MethodTimerAdapter3 (line 34) | public MethodTimerAdapter3(int api, int access, String name, String ...
      method visitCode (line 40) | @Override
      method visitInsn (line 51) | @Override

FILE: src/main/java/lsieun/asm/core/MethodTimerVisitor4.java
  class MethodTimerVisitor4 (line 10) | public class MethodTimerVisitor4 extends ClassVisitor {
    method MethodTimerVisitor4 (line 11) | public MethodTimerVisitor4(int api, ClassVisitor classVisitor) {
    method visitMethod (line 15) | @Override
    class MethodTimerAdapter4 (line 28) | private static class MethodTimerAdapter4 extends AdviceAdapter {
      method MethodTimerAdapter4 (line 31) | public MethodTimerAdapter4(int api, MethodVisitor mv, int access, St...
      method onMethodEnter (line 35) | @Override
      method onMethodExit (line 42) | @Override

FILE: src/main/java/lsieun/asm/core/SuperPackageAttribute.java
  class SuperPackageAttribute (line 5) | public class SuperPackageAttribute extends Attribute {
    method SuperPackageAttribute (line 8) | public SuperPackageAttribute() {
    method SuperPackageAttribute (line 12) | public SuperPackageAttribute(String name) {
    method read (line 17) | @Override
    method write (line 23) | @Override
    method toString (line 29) | @Override

FILE: src/main/java/lsieun/asm/core/counter/ClassCounterVisitor.java
  class ClassCounterVisitor (line 9) | public class ClassCounterVisitor extends ClassVisitor {
    method ClassCounterVisitor (line 13) | public ClassCounterVisitor(int api, ClassVisitor cv) {
    method visit (line 17) | @Override
    method visitMethod (line 24) | @Override

FILE: src/main/java/lsieun/asm/core/counter/MethodCounterAdapter.java
  class MethodCounterAdapter (line 7) | public class MethodCounterAdapter extends MethodVisitor {
    method MethodCounterAdapter (line 11) | public MethodCounterAdapter(int api, MethodVisitor mv, String owner, S...
    method visitCode (line 17) | @Override

FILE: src/main/java/lsieun/asm/core/empty/EmptyAnnotationVisitor.java
  class EmptyAnnotationVisitor (line 5) | public class EmptyAnnotationVisitor extends AnnotationVisitor {
    method EmptyAnnotationVisitor (line 6) | public EmptyAnnotationVisitor(int api, AnnotationVisitor annotationVis...

FILE: src/main/java/lsieun/asm/core/empty/EmptyClassVisitor.java
  class EmptyClassVisitor (line 5) | public class EmptyClassVisitor extends ClassVisitor {
    method EmptyClassVisitor (line 6) | public EmptyClassVisitor(int api, ClassVisitor classVisitor) {
    method visitModule (line 10) | @Override
    method visitAnnotation (line 16) | @Override
    method visitTypeAnnotation (line 22) | @Override
    method visitRecordComponent (line 28) | @Override
    method visitField (line 34) | @Override
    method visitMethod (line 40) | @Override

FILE: src/main/java/lsieun/asm/core/empty/EmptyFieldVisitor.java
  class EmptyFieldVisitor (line 5) | public class EmptyFieldVisitor extends FieldVisitor {
    method EmptyFieldVisitor (line 6) | public EmptyFieldVisitor(int api, FieldVisitor fieldVisitor) {

FILE: src/main/java/lsieun/asm/core/empty/EmptyMethodVisitor.java
  class EmptyMethodVisitor (line 5) | public class EmptyMethodVisitor extends MethodVisitor {
    method EmptyMethodVisitor (line 6) | public EmptyMethodVisitor(int api, MethodVisitor methodVisitor) {

FILE: src/main/java/lsieun/asm/core/empty/EmptyModuleVisitor.java
  class EmptyModuleVisitor (line 5) | public class EmptyModuleVisitor extends ModuleVisitor {
    method EmptyModuleVisitor (line 6) | public EmptyModuleVisitor(int api, ModuleVisitor moduleVisitor) {

FILE: src/main/java/lsieun/asm/core/empty/EmptyRecordComponentVisitor.java
  class EmptyRecordComponentVisitor (line 5) | public class EmptyRecordComponentVisitor extends RecordComponentVisitor {
    method EmptyRecordComponentVisitor (line 6) | public EmptyRecordComponentVisitor(int api, RecordComponentVisitor rec...

FILE: src/main/java/lsieun/asm/core/info/InfoClassVisitor.java
  class InfoClassVisitor (line 9) | public class InfoClassVisitor extends ClassVisitor {
    method InfoClassVisitor (line 10) | public InfoClassVisitor(int api, ClassVisitor classVisitor) {
    method visit (line 14) | @Override
    method visitAttribute (line 21) | @Override
    method visitField (line 29) | @Override
    method visitMethod (line 38) | @Override
    method visitEnd (line 47) | @Override
    method getAccess (line 54) | private String getAccess(int access) {

FILE: src/main/java/lsieun/asm/core/info/InfoFieldVisitor.java
  class InfoFieldVisitor (line 5) | public class InfoFieldVisitor extends FieldVisitor {
    method InfoFieldVisitor (line 6) | public InfoFieldVisitor(int api, FieldVisitor fieldVisitor) {
    method visitEnd (line 10) | @Override

FILE: src/main/java/lsieun/asm/core/info/InfoMethodVisitor.java
  class InfoMethodVisitor (line 7) | public class InfoMethodVisitor extends MethodVisitor {
    method InfoMethodVisitor (line 8) | public InfoMethodVisitor(int api, MethodVisitor methodVisitor) {
    method visitCode (line 12) | @Override
    method visitInsn (line 19) | @Override
    method visitIntInsn (line 26) | @Override
    method visitVarInsn (line 33) | @Override
    method visitTypeInsn (line 40) | @Override
    method visitFieldInsn (line 47) | @Override
    method visitMethodInsn (line 54) | @Override
    method visitJumpInsn (line 61) | @Override
    method visitLabel (line 68) | @Override
    method visitLdcInsn (line 75) | @Override
    method visitIincInsn (line 82) | @Override
    method visitMaxs (line 89) | @Override
    method visitEnd (line 96) | @Override

FILE: src/main/java/lsieun/asm/core/timer/ClassTimerVisitor.java
  class ClassTimerVisitor (line 9) | public class ClassTimerVisitor extends ClassVisitor {
    method ClassTimerVisitor (line 13) | public ClassTimerVisitor(int api, ClassVisitor cv) {
    method visit (line 17) | @Override
    method visitMethod (line 24) | @Override
    method visitEnd (line 33) | @Override

FILE: src/main/java/lsieun/asm/core/timer/MethodTimerAdapter.java
  class MethodTimerAdapter (line 7) | public class MethodTimerAdapter extends MethodVisitor {
    method MethodTimerAdapter (line 10) | public MethodTimerAdapter(int api, MethodVisitor mv, String owner) {
    method visitCode (line 15) | @Override
    method visitInsn (line 24) | @Override

FILE: src/main/java/lsieun/asm/template/CheckMethodAnnotationVisitor.java
  class CheckMethodAnnotationVisitor (line 10) | public class CheckMethodAnnotationVisitor extends ClassVisitor {
    method CheckMethodAnnotationVisitor (line 14) | public CheckMethodAnnotationVisitor(int api, ClassVisitor classVisitor) {
    method visitMethod (line 18) | @Override
    class CheckMethodAnnotationAdapter (line 25) | private class CheckMethodAnnotationAdapter extends MethodVisitor {
      method CheckMethodAnnotationAdapter (line 29) | public CheckMethodAnnotationAdapter(int api, MethodVisitor methodVis...
      method visitAnnotation (line 35) | @Override

FILE: src/main/java/lsieun/asm/template/ClassAddAnnotationVisitor.java
  class ClassAddAnnotationVisitor (line 5) | public class ClassAddAnnotationVisitor extends ClassVisitor {
    method ClassAddAnnotationVisitor (line 9) | public ClassAddAnnotationVisitor(int api, ClassVisitor classVisitor, S...
    method visitAnnotation (line 14) | @Override
    method visitNestMember (line 22) | @Override
    method visitInnerClass (line 28) | @Override
    method visitRecordComponent (line 34) | @Override
    method visitField (line 40) | @Override
    method visitMethod (line 46) | @Override
    method visitEnd (line 52) | @Override
    method addAnnotation (line 58) | private void addAnnotation() {

FILE: src/main/java/lsieun/asm/template/ClassAddCustomAttributeVisitor.java
  class ClassAddCustomAttributeVisitor (line 6) | public class ClassAddCustomAttributeVisitor extends ClassVisitor {
    method ClassAddCustomAttributeVisitor (line 11) | public ClassAddCustomAttributeVisitor(int api, ClassVisitor classVisit...
    method visitAttribute (line 18) | @Override
    method visitNestMember (line 26) | @Override
    method visitInnerClass (line 32) | @Override
    method visitRecordComponent (line 38) | @Override
    method visitField (line 44) | @Override
    method visitMethod (line 50) | @Override
    method visitEnd (line 56) | @Override
    method addAttribute (line 62) | private void addAttribute() {

FILE: src/main/java/lsieun/asm/template/ClassAddFieldVisitor.java
  class ClassAddFieldVisitor (line 6) | public class ClassAddFieldVisitor extends ClassVisitor {
    method ClassAddFieldVisitor (line 12) | public ClassAddFieldVisitor(int api, ClassVisitor classVisitor, int fi...
    method visitField (line 19) | @Override
    method visitEnd (line 27) | @Override

FILE: src/main/java/lsieun/asm/template/ClassAddInterfaceVisitor.java
  class ClassAddInterfaceVisitor (line 9) | public class ClassAddInterfaceVisitor extends ClassVisitor {
    method ClassAddInterfaceVisitor (line 12) | public ClassAddInterfaceVisitor(int api, ClassVisitor cv, String[] new...
    method visit (line 17) | @Override

FILE: src/main/java/lsieun/asm/template/ClassAddMethodVisitor.java
  class ClassAddMethodVisitor (line 6) | public abstract class ClassAddMethodVisitor extends ClassVisitor {
    method ClassAddMethodVisitor (line 14) | public ClassAddMethodVisitor(int api, ClassVisitor cv, int methodAcces...
    method visitMethod (line 25) | @Override
    method visitEnd (line 33) | @Override
    method generateMethodBody (line 46) | protected abstract void generateMethodBody(MethodVisitor mv);

FILE: src/main/java/lsieun/asm/template/ClassGetAttributeContentVisitor.java
  class ClassGetAttributeContentVisitor (line 7) | public class ClassGetAttributeContentVisitor extends ClassVisitor {
    method ClassGetAttributeContentVisitor (line 10) | public ClassGetAttributeContentVisitor(int api, ClassVisitor classVisi...
    method visit (line 14) | @Override
    method visitField (line 20) | @Override
    method visitMethod (line 26) | @Override
    method getAttributeContent (line 32) | public String getAttributeContent() {

FILE: src/main/java/lsieun/asm/template/ClassMergeVisitor.java
  class ClassMergeVisitor (line 10) | public class ClassMergeVisitor extends ClassVisitor {
    method ClassMergeVisitor (line 13) | public ClassMergeVisitor(int api, ClassVisitor classVisitor, ClassNode...
    method visitEnd (line 18) | @Override

FILE: src/main/java/lsieun/asm/template/ClassMergeVisitorRun.java
  class ClassMergeVisitorRun (line 13) | public class ClassMergeVisitorRun {
    method main (line 14) | public static void main(String[] args) {
    method getClassNode (line 48) | public static ClassNode getClassNode(byte[] bytes) {
    method rename (line 55) | public static byte[] rename(String origin_name, String target_name) {
    method getFilePath (line 75) | public static String getFilePath(String internalName) {

FILE: src/main/java/lsieun/asm/template/ClassPrintAnnotationVisitor.java
  class ClassPrintAnnotationVisitor (line 8) | public class ClassPrintAnnotationVisitor extends ClassVisitor {
    method ClassPrintAnnotationVisitor (line 11) | public ClassPrintAnnotationVisitor(int api, ClassVisitor classVisitor) {
    method visit (line 15) | @Override
    method visitAnnotation (line 21) | @Override
    method visitMethod (line 32) | @Override
    class MethodPrintAnnotationAdapter (line 40) | private static class MethodPrintAnnotationAdapter extends MethodVisitor {
      method MethodPrintAnnotationAdapter (line 46) | public MethodPrintAnnotationAdapter(int api, MethodVisitor methodVis...
      method visitAnnotation (line 53) | @Override
    class AnnotationPrinter (line 66) | private static class AnnotationPrinter extends AnnotationVisitor {
      method AnnotationPrinter (line 67) | public AnnotationPrinter(int api, AnnotationVisitor annotationVisito...
      method visit (line 71) | @Override
      method visitEnum (line 81) | @Override
      method visitAnnotation (line 91) | @Override
      method visitArray (line 101) | @Override

FILE: src/main/java/lsieun/asm/template/ClassPrintParameterVisitor.java
  class ClassPrintParameterVisitor (line 10) | public class ClassPrintParameterVisitor extends ClassVisitor {
    method ClassPrintParameterVisitor (line 11) | public ClassPrintParameterVisitor(int api, ClassVisitor classVisitor) {
    method visitMethod (line 15) | @Override
    class MethodPrintParameterAdapter (line 28) | public static class MethodPrintParameterAdapter extends AdviceAdapter {
      method MethodPrintParameterAdapter (line 29) | public MethodPrintParameterAdapter(int api, MethodVisitor mv, int ac...
      method onMethodEnter (line 33) | @Override
      method onMethodExit (line 46) | @Override
      method printMessage (line 71) | private void printMessage(String str) {
      method printValueOnStack (line 76) | private void printValueOnStack(String descriptor) {

FILE: src/main/java/lsieun/asm/template/ClassRemoveFieldVisitor.java
  class ClassRemoveFieldVisitor (line 6) | public class ClassRemoveFieldVisitor extends ClassVisitor {
    method ClassRemoveFieldVisitor (line 10) | public ClassRemoveFieldVisitor(int api, ClassVisitor cv, String fieldN...
    method visitField (line 16) | @Override

FILE: src/main/java/lsieun/asm/template/ClassRemoveMethodVisitor.java
  class ClassRemoveMethodVisitor (line 6) | public class ClassRemoveMethodVisitor extends ClassVisitor {
    method ClassRemoveMethodVisitor (line 10) | public ClassRemoveMethodVisitor(int api, ClassVisitor cv, String metho...
    method visitMethod (line 16) | @Override

FILE: src/main/java/lsieun/asm/template/ClassRenameAdapter.java
  class ClassRenameAdapter (line 7) | public class ClassRenameAdapter extends ClassVisitor {
    method ClassRenameAdapter (line 11) | public ClassRenameAdapter(int api, ClassVisitor classVisitor, String o...
    method visit (line 17) | @Override
    method visitField (line 27) | @Override
    method visitMethod (line 38) | @Override
    method getDescriptor (line 53) | public String getDescriptor(String internalName) {

FILE: src/main/java/lsieun/asm/template/ClassRenameAdapterRun.java
  class ClassRenameAdapterRun (line 10) | public class ClassRenameAdapterRun {
    method main (line 11) | public static void main(String[] args) {
    method getFilePath (line 36) | public static String getFilePath(String internalName) {

FILE: src/main/java/lsieun/asm/template/ClassReplaceMethodBodyVisitor.java
  class ClassReplaceMethodBodyVisitor (line 6) | public abstract class ClassReplaceMethodBodyVisitor extends ClassVisitor {
    method ClassReplaceMethodBodyVisitor (line 12) | public ClassReplaceMethodBodyVisitor(int api, ClassVisitor cv, String ...
    method ClassReplaceMethodBodyVisitor (line 16) | public ClassReplaceMethodBodyVisitor(int api, ClassVisitor cv, String ...
    method visit (line 23) | @Override
    method visitMethod (line 29) | @Override
    method getNewName (line 49) | protected String getNewName(String name) {
    method generateNewMethod (line 53) | private void generateNewMethod(int access, String name, String descrip...
    method generateMethodBody (line 60) | protected abstract void generateMethodBody(MethodVisitor mv);

FILE: src/main/java/lsieun/asm/template/CustomAttribute.java
  class CustomAttribute (line 8) | public class CustomAttribute extends Attribute {
    method CustomAttribute (line 16) | public CustomAttribute(String type, byte[] info) {
    method read (line 21) | @Override
    method write (line 32) | @Override
    method toString (line 40) | @Override

FILE: src/main/java/lsieun/asm/template/FieldAccessAdapter.java
  class FieldAccessAdapter (line 8) | public class FieldAccessAdapter extends ClassVisitor {
    method FieldAccessAdapter (line 11) | public FieldAccessAdapter(int api, ClassVisitor cv, List<Info> list) {
    method visitMethod (line 16) | @Override

FILE: src/main/java/lsieun/asm/template/FieldAccessAdapterRun.java
  class FieldAccessAdapterRun (line 13) | public class FieldAccessAdapterRun {
    method main (line 14) | public static void main(String[] args) {

FILE: src/main/java/lsieun/asm/template/FieldAccessConverter.java
  class FieldAccessConverter (line 8) | public class FieldAccessConverter extends MethodVisitor {
    method FieldAccessConverter (line 11) | public FieldAccessConverter(int api, MethodVisitor mv, List<Info> list) {
    method visitFieldInsn (line 21) | @Override
    method matchingInfo (line 31) | private Info matchingInfo(int opcode, String owner, String name, Strin...

FILE: src/main/java/lsieun/asm/template/Info.java
  class Info (line 3) | public class Info {
    method Info (line 14) | public Info(

FILE: src/main/java/lsieun/asm/template/MethodCallAdapter.java
  class MethodCallAdapter (line 8) | public class MethodCallAdapter extends ClassVisitor {
    method MethodCallAdapter (line 11) | public MethodCallAdapter(int api, ClassVisitor cv, List<Info> list) {
    method visitMethod (line 16) | @Override

FILE: src/main/java/lsieun/asm/template/MethodCallAdapterRun.java
  class MethodCallAdapterRun (line 13) | public class MethodCallAdapterRun {
    method main (line 14) | public static void main(String[] args) {

FILE: src/main/java/lsieun/asm/template/MethodCallConverter.java
  class MethodCallConverter (line 8) | public class MethodCallConverter extends MethodVisitor {
    method MethodCallConverter (line 11) | public MethodCallConverter(int api, MethodVisitor mv, List<Info> list) {
    method visitMethodInsn (line 21) | @Override
    method matchingInfo (line 31) | private Info matchingInfo(int opcode, String owner, String name, Strin...

FILE: src/main/java/lsieun/asm/template/MethodEnteringAdapter.java
  class MethodEnteringAdapter (line 6) | public class MethodEnteringAdapter extends AdviceAdapter {
    method MethodEnteringAdapter (line 9) | public MethodEnteringAdapter(int api, MethodVisitor mv, int access, St...
    method onMethodEnter (line 14) | @Override

FILE: src/main/java/lsieun/asm/template/MethodEnteringVisitor.java
  class MethodEnteringVisitor (line 6) | public class MethodEnteringVisitor extends ClassVisitor {
    method MethodEnteringVisitor (line 7) | public MethodEnteringVisitor(int api, ClassVisitor cv) {
    method visitMethod (line 11) | @Override

FILE: src/main/java/lsieun/asm/template/MethodEnteringVisitorRun.java
  class MethodEnteringVisitorRun (line 10) | public class MethodEnteringVisitorRun {
    method main (line 11) | public static void main(String[] args) {

FILE: src/main/java/lsieun/asm/template/MethodExitingAdapter.java
  class MethodExitingAdapter (line 6) | public class MethodExitingAdapter extends ClassVisitor {
    method MethodExitingAdapter (line 7) | public MethodExitingAdapter(int api, ClassVisitor cv) {
    method visitMethod (line 11) | @Override

FILE: src/main/java/lsieun/asm/template/MethodExitingAdapterRun.java
  class MethodExitingAdapterRun (line 10) | public class MethodExitingAdapterRun {
    method main (line 11) | public static void main(String[] args) {

FILE: src/main/java/lsieun/asm/template/MethodExitingConverter.java
  class MethodExitingConverter (line 7) | public class MethodExitingConverter extends AdviceAdapter {
    method MethodExitingConverter (line 10) | protected MethodExitingConverter(int api, MethodVisitor mv, int access...
    method onMethodExit (line 15) | @Override

FILE: src/main/java/lsieun/asm/template/MethodFinallyAdapter.java
  class MethodFinallyAdapter (line 6) | public class MethodFinallyAdapter extends ClassVisitor {
    method MethodFinallyAdapter (line 7) | public MethodFinallyAdapter(int api, ClassVisitor cv) {
    method visitMethod (line 11) | @Override

FILE: src/main/java/lsieun/asm/template/MethodFinallyAdapterRun.java
  class MethodFinallyAdapterRun (line 10) | public class MethodFinallyAdapterRun {
    method main (line 11) | public static void main(String[] args) {

FILE: src/main/java/lsieun/asm/template/MethodFinallyConverter.java
  class MethodFinallyConverter (line 8) | public class MethodFinallyConverter extends AdviceAdapter {
    method MethodFinallyConverter (line 13) | protected MethodFinallyConverter(int api, MethodVisitor mv, int access...
    method visitCode (line 18) | @Override
    method visitMaxs (line 24) | @Override
    method onMethodExit (line 36) | @Override
    method onFinally (line 43) | private void onFinally() {

FILE: src/main/java/lsieun/asm/template/MethodPrintInstructionAdapter.java
  class MethodPrintInstructionAdapter (line 11) | public class MethodPrintInstructionAdapter extends MethodVisitor {
    method MethodPrintInstructionAdapter (line 18) | public MethodPrintInstructionAdapter(int api, MethodVisitor methodVisi...
    method visitCode (line 24) | @Override
    method visitVarInsn (line 35) | @Override
    method visitInsn (line 87) | @Override
    method visitIincInsn (line 95) | @Override
    method visitIntInsn (line 104) | @Override
    method visitJumpInsn (line 113) | @Override
    method visitLdcInsn (line 156) | @Override
    method visitTableSwitchInsn (line 164) | @Override
    method visitLookupSwitchInsn (line 172) | @Override
    method visitMultiANewArrayInsn (line 180) | @Override
    method visitFieldInsn (line 189) | @Override
    method visitMethodInsn (line 198) | @Override
    method visitInvokeDynamicInsn (line 207) | @Override
    method visitTypeInsn (line 216) | @Override
    method printMessage (line 224) | private void printMessage(String message) {
    method dup (line 230) | private void dup(Type t) {
    method printValueOnStack (line 240) | private void printValueOnStack(Type t) {
    method dupAndPrintValueOnStack (line 255) | private void dupAndPrintValueOnStack(Type t) {

FILE: src/main/java/lsieun/asm/template/MethodPrintInstructionVisitor.java
  class MethodPrintInstructionVisitor (line 9) | public class MethodPrintInstructionVisitor extends ClassVisitor {
    method MethodPrintInstructionVisitor (line 10) | public MethodPrintInstructionVisitor(int api, ClassVisitor classVisito...
    method visitMethod (line 14) | @Override

FILE: src/main/java/lsieun/asm/template/MethodWithSameTryCatchLogicVisitor.java
  class MethodWithSameTryCatchLogicVisitor (line 12) | public class MethodWithSameTryCatchLogicVisitor extends ClassVisitor {
    method MethodWithSameTryCatchLogicVisitor (line 13) | public MethodWithSameTryCatchLogicVisitor(int api, ClassVisitor classV...
    method visitMethod (line 17) | @Override
    class MethodWithSameTryCatchLogicAdapter (line 31) | private static class MethodWithSameTryCatchLogicAdapter extends Method...
      method MethodWithSameTryCatchLogicAdapter (line 34) | public MethodWithSameTryCatchLogicAdapter(int api, MethodVisitor met...
      method visitTryCatchBlock (line 38) | @Override
      method visitLabel (line 49) | @Override

FILE: src/main/java/lsieun/asm/template/MethodWithWholeTryCatchVisitor.java
  class MethodWithWholeTryCatchVisitor (line 7) | public class MethodWithWholeTryCatchVisitor extends ClassVisitor {
    method MethodWithWholeTryCatchVisitor (line 11) | public MethodWithWholeTryCatchVisitor(int api, ClassVisitor classVisit...
    method visitMethod (line 17) | @Override
    class MethodWithWholeTryCatchAdapter (line 30) | private static class MethodWithWholeTryCatchAdapter extends MethodVisi...
      method MethodWithWholeTryCatchAdapter (line 38) | public MethodWithWholeTryCatchAdapter(int api, MethodVisitor methodV...
      method visitCode (line 44) | public void visitCode() {
      method visitMaxs (line 53) | @Override
      method getLocalIndex (line 76) | private int getLocalIndex() {

FILE: src/main/java/lsieun/asm/template/RefRenameAdapter.java
  class RefRenameAdapter (line 6) | public class RefRenameAdapter extends MethodVisitor {
    method RefRenameAdapter (line 10) | public RefRenameAdapter(int api, MethodVisitor mv, String oldOwner, St...
    method visitLdcInsn (line 16) | @Override
    method getDescriptor (line 28) | public String getDescriptor(String internalName) {
    method visitFieldInsn (line 32) | @Override
    method visitMethodInsn (line 42) | @Override

FILE: src/main/java/lsieun/asm/template/RemoveSyntheticVisitor.java
  class RemoveSyntheticVisitor (line 8) | public class RemoveSyntheticVisitor extends ClassVisitor {
    method RemoveSyntheticVisitor (line 9) | public RemoveSyntheticVisitor(int api, ClassVisitor classVisitor) {
    method visit (line 13) | @Override
    method visitField (line 18) | @Override
    method visitMethod (line 23) | @Override

FILE: src/main/java/lsieun/asm/tree/ChangeMemberNameBasedOnAnnotationNode.java
  class ChangeMemberNameBasedOnAnnotationNode (line 10) | public class ChangeMemberNameBasedOnAnnotationNode extends ClassNode {
    method ChangeMemberNameBasedOnAnnotationNode (line 13) | public ChangeMemberNameBasedOnAnnotationNode(int api, ClassVisitor cv,...
    method visitEnd (line 19) | @Override
    method exists (line 40) | private boolean exists(String name, List<AnnotationNode> annotations) {

FILE: src/main/java/lsieun/asm/tree/ChangeThisNode.java
  class ChangeThisNode (line 13) | public class ChangeThisNode extends ClassNode {
    method ChangeThisNode (line 14) | public ChangeThisNode(int api, ClassVisitor cv) {
    method visitEnd (line 19) | @Override
    class ChangeThisAdapter (line 51) | private static class ChangeThisAdapter extends MethodVisitor {
      method ChangeThisAdapter (line 57) | public ChangeThisAdapter(int api, MethodVisitor mv, int access, Stri...
      method visitCode (line 65) | @Override
      method visitInsn (line 103) | @Override
      method getBackUpIndex (line 157) | private int getBackUpIndex(int localIndex) {

FILE: src/main/java/lsieun/asm/tree/ClassAddCustomAttributeNode.java
  class ClassAddCustomAttributeNode (line 13) | public class ClassAddCustomAttributeNode extends ClassNode {
    method ClassAddCustomAttributeNode (line 16) | public ClassAddCustomAttributeNode(int api, ClassVisitor cv, String at...
    method visitEnd (line 22) | @Override

FILE: src/main/java/lsieun/asm/tree/ClassAddFieldNode.java
  class ClassAddFieldNode (line 8) | public class ClassAddFieldNode extends ClassNode {
    method ClassAddFieldNode (line 13) | public ClassAddFieldNode(int api, ClassVisitor cv,
    method visitEnd (line 22) | @Override
    class ClassAddFieldTransformer (line 37) | private static class ClassAddFieldTransformer extends ClassTransformer {
      method ClassAddFieldTransformer (line 42) | public ClassAddFieldTransformer(ClassTransformer ct, int fieldAccess...
      method transform (line 49) | @Override

FILE: src/main/java/lsieun/asm/tree/ClassAddMethodNode.java
  class ClassAddMethodNode (line 10) | public class ClassAddMethodNode extends ClassNode {
    method ClassAddMethodNode (line 16) | public ClassAddMethodNode(int api, ClassVisitor cv,
    method visitEnd (line 27) | @Override
    class ClassAddMethodTransformer (line 42) | private static class ClassAddMethodTransformer extends ClassTransformer {
      method ClassAddMethodTransformer (line 48) | public ClassAddMethodTransformer(ClassTransformer ct,
      method transform (line 58) | @Override

FILE: src/main/java/lsieun/asm/tree/ClassAddTimerNode.java
  class ClassAddTimerNode (line 9) | public class ClassAddTimerNode extends ClassNode {
    method ClassAddTimerNode (line 10) | public ClassAddTimerNode(int api, ClassVisitor cv) {
    method visitEnd (line 15) | @Override
    class ClassAddTimerTransformer (line 30) | private static class ClassAddTimerTransformer extends ClassTransformer {
      method ClassAddTimerTransformer (line 31) | public ClassAddTimerTransformer(ClassTransformer ct) {
      method transform (line 35) | @Override

FILE: src/main/java/lsieun/asm/tree/ClassRemoveFieldNode.java
  class ClassRemoveFieldNode (line 7) | public class ClassRemoveFieldNode extends ClassNode {
    method ClassRemoveFieldNode (line 11) | public ClassRemoveFieldNode(int api, ClassVisitor cv, String fieldName...
    method visitEnd (line 18) | @Override
    class ClassRemoveFieldTransformer (line 33) | private static class ClassRemoveFieldTransformer extends ClassTransfor...
      method ClassRemoveFieldTransformer (line 37) | public ClassRemoveFieldTransformer(ClassTransformer ct, String field...
      method transform (line 43) | @Override

FILE: src/main/java/lsieun/asm/tree/ClassRemoveMethodNode.java
  class ClassRemoveMethodNode (line 7) | public class ClassRemoveMethodNode extends ClassNode {
    method ClassRemoveMethodNode (line 11) | public ClassRemoveMethodNode(int api, ClassVisitor cv, String methodNa...
    method visitEnd (line 18) | @Override
    class ClassRemoveMethodTransformer (line 33) | private static class ClassRemoveMethodTransformer extends ClassTransfo...
      method ClassRemoveMethodTransformer (line 37) | public ClassRemoveMethodTransformer(ClassTransformer ct, String meth...
      method transform (line 43) | @Override

FILE: src/main/java/lsieun/asm/tree/MixCore2TreeVisitor.java
  class MixCore2TreeVisitor (line 9) | public class MixCore2TreeVisitor extends ClassVisitor {
    method MixCore2TreeVisitor (line 10) | public MixCore2TreeVisitor(int api, ClassVisitor classVisitor) {
    method visitMethod (line 14) | @Override
    class MethodEnterNode (line 27) | private static class MethodEnterNode extends MethodNode {
      method MethodEnterNode (line 28) | public MethodEnterNode(int api, int access, String name, String desc...
      method visitEnd (line 35) | @Override

FILE: src/main/java/lsieun/asm/tree/MixTree2CoreNode.java
  class MixTree2CoreNode (line 11) | public class MixTree2CoreNode extends ClassNode {
    method MixTree2CoreNode (line 12) | public MixTree2CoreNode(int api, ClassVisitor cv) {
    method visitEnd (line 17) | @Override

FILE: src/main/java/lsieun/asm/tree/OptimizeJumpNode.java
  class OptimizeJumpNode (line 9) | public class OptimizeJumpNode extends ClassNode {
    method OptimizeJumpNode (line 10) | public OptimizeJumpNode(int api, ClassVisitor cv) {
    method visitEnd (line 15) | @Override
    class MethodOptimizeJumpTransformer (line 39) | private static class MethodOptimizeJumpTransformer extends MethodTrans...
      method MethodOptimizeJumpTransformer (line 40) | public MethodOptimizeJumpTransformer(MethodTransformer mt) {
      method transform (line 44) | @Override

FILE: src/main/java/lsieun/asm/tree/RemoveGetFieldPutFieldNode.java
  class RemoveGetFieldPutFieldNode (line 11) | public class RemoveGetFieldPutFieldNode extends ClassNode {
    method RemoveGetFieldPutFieldNode (line 12) | public RemoveGetFieldPutFieldNode(int api, ClassVisitor cv) {
    method visitEnd (line 17) | @Override
    class MethodRemoveGetFieldPutFieldTransformer (line 41) | private static class MethodRemoveGetFieldPutFieldTransformer extends M...
      method MethodRemoveGetFieldPutFieldTransformer (line 42) | public MethodRemoveGetFieldPutFieldTransformer(MethodTransformer mt) {
      method transform (line 46) | @Override
      method getNext (line 78) | private static AbstractInsnNode getNext(AbstractInsnNode insn) {
      method isALOAD0 (line 88) | private static boolean isALOAD0(AbstractInsnNode insnNode) {
      method sameField (line 92) | private static boolean sameField(AbstractInsnNode oneInsnNode, Abstr...

FILE: src/main/java/lsieun/asm/tree/my/MyClassNode.java
  class MyClassNode (line 6) | public class MyClassNode extends ClassNode {
    method MyClassNode (line 7) | public MyClassNode(int api, ClassVisitor cv) {
    method visitEnd (line 12) | @Override

FILE: src/main/java/lsieun/asm/tree/my/MyClassVisitor.java
  class MyClassVisitor (line 6) | public class MyClassVisitor extends ClassVisitor {
    method MyClassVisitor (line 9) | public MyClassVisitor(int api, ClassVisitor classVisitor) {
    method visitEnd (line 14) | @Override

FILE: src/main/java/lsieun/asm/tree/my/MyMethodAdapter.java
  class MyMethodAdapter (line 6) | public class MyMethodAdapter extends MethodVisitor {
    method MyMethodAdapter (line 9) | public MyMethodAdapter(int api, int access, String name, String desc,
    method visitEnd (line 15) | @Override

FILE: src/main/java/lsieun/asm/tree/my/MyMethodNode.java
  class MyMethodNode (line 6) | public class MyMethodNode extends MethodNode {
    method MyMethodNode (line 7) | public MyMethodNode(int access, String name, String descriptor,
    method visitEnd (line 14) | @Override

FILE: src/main/java/lsieun/asm/tree/transformer/ClassTransformer.java
  class ClassTransformer (line 5) | public abstract class ClassTransformer {
    method ClassTransformer (line 8) | public ClassTransformer(ClassTransformer ct) {
    method transform (line 12) | public void transform(ClassNode cn) {

FILE: src/main/java/lsieun/asm/tree/transformer/MethodTransformer.java
  class MethodTransformer (line 5) | public abstract class MethodTransformer {
    method MethodTransformer (line 8) | public MethodTransformer(MethodTransformer mt) {
    method transform (line 12) | public void transform(MethodNode mn) {

FILE: src/main/java/lsieun/asm/util/CheckClassAdapterExample01Generate.java
  class CheckClassAdapterExample01Generate (line 8) | public class CheckClassAdapterExample01Generate {
    method main (line 9) | public static void main(String[] args) throws Exception {
    method dump (line 20) | public static byte[] dump() throws Exception {

FILE: src/main/java/lsieun/asm/util/CheckClassAdapterExample02Generate.java
  class CheckClassAdapterExample02Generate (line 10) | public class CheckClassAdapterExample02Generate {
    method main (line 11) | public static void main(String[] args) throws Exception {
    method dump (line 26) | public static byte[] dump() throws Exception {

FILE: src/main/java/lsieun/asm/util/CodeUtils.java
  class CodeUtils (line 9) | public class CodeUtils {
    method generate (line 10) | public static void generate(ClassVisitor cv) {

FILE: src/main/java/lsieun/asm/util/TraceClassVisitorExample01Generate.java
  class TraceClassVisitorExample01Generate (line 13) | public class TraceClassVisitorExample01Generate {
    method main (line 14) | public static void main(String[] args) throws Exception {
    method dump (line 25) | public static byte[] dump() throws Exception {

FILE: src/main/java/lsieun/asm/util/TraceClassVisitorExample02Transform.java
  class TraceClassVisitorExample02Transform (line 13) | public class TraceClassVisitorExample02Transform {
    method main (line 14) | public static void main(String[] args) {

FILE: src/main/java/lsieun/asm/util/TraceClassVisitorExample03.java
  class TraceClassVisitorExample03 (line 9) | @SuppressWarnings("Duplicates")
    method main (line 11) | public static void main(String[] args) {

FILE: src/main/java/lsieun/asm/util/TreePrinter.java
  class TreePrinter (line 11) | public class TreePrinter extends Printer {
    method TreePrinter (line 48) | public TreePrinter() {
    method TreePrinter (line 52) | public TreePrinter(int api, String visitorVariableName) {
    method visit (line 57) | @Override
    method visitSource (line 97) | @Override
    method visitOuterClass (line 102) | @Override
    method visitClassAnnotation (line 107) | @Override
    method visitClassAttribute (line 112) | @Override
    method visitInnerClass (line 117) | @Override
    method visitField (line 122) | @Override
    method visitMethod (line 140) | @Override
    method visitClassEnd (line 173) | @Override
    method visit (line 188) | @Override
    method visitEnum (line 193) | @Override
    method visitAnnotation (line 198) | @Override
    method visitArray (line 203) | @Override
    method visitAnnotationEnd (line 208) | @Override
    method visitFieldAnnotation (line 213) | @Override
    method visitFieldAttribute (line 218) | @Override
    method visitFieldEnd (line 223) | @Override
    method visitAnnotationDefault (line 228) | @Override
    method visitMethodAnnotation (line 233) | @Override
    method visitParameterAnnotation (line 238) | @Override
    method visitMethodAttribute (line 243) | @Override
    method visitCode (line 248) | @Override
    method visitFrame (line 253) | @Override
    method visitInsn (line 258) | @Override
    method visitIntInsn (line 266) | @Override
    method visitVarInsn (line 274) | @Override
    method visitTypeInsn (line 282) | @Override
    method visitFieldInsn (line 290) | @Override
    method visitMethodInsn (line 298) | @Override
    method visitInvokeDynamicInsn (line 306) | @Override
    method visitJumpInsn (line 324) | @Override
    method visitLabel (line 338) | @Override
    method visitLdcInsn (line 348) | @Override
    method visitIincInsn (line 356) | @Override
    method visitTableSwitchInsn (line 364) | @Override
    method visitLookupSwitchInsn (line 387) | @Override
    method visitMultiANewArrayInsn (line 417) | @Override
    method visitTryCatchBlock (line 425) | @Override
    method visitLocalVariable (line 446) | @Override
    method visitLineNumber (line 451) | @Override
    method visitMaxs (line 456) | @Override
    method visitMethodEnd (line 466) | @Override
    method createVariable (line 474) | protected TreePrinter createVariable(String visitorVariableName) {
    method toAccessFlags (line 478) | private String toAccessFlags(final int accessFlags) {
    method toConstant (line 647) | protected String toConstant(final Object value) {
    method declareLabelNode (line 780) | protected String declareLabelNode(final Label label) {
    method toLabelName (line 796) | protected String toLabelName(final Label label) {

FILE: src/main/java/lsieun/classfile/CPInfo.java
  class CPInfo (line 3) | public class CPInfo {

FILE: src/main/java/lsieun/classfile/ClassFile.java
  class ClassFile (line 5) | public class ClassFile {
    method ClassFile (line 28) | public ClassFile(byte[] classFileBuffer) {
    method ClassFile (line 32) | public ClassFile(byte[] classFileBuffer, int classFileOffset, int clas...
    method getCode (line 136) | public byte[] getCode(int methodIndex) {
    method getAttributeSize (line 159) | private int getAttributeSize(int attribute_info_offset) {
    method readByte (line 166) | public int readByte(final int offset) {
    method readUnsignedShort (line 170) | public int readUnsignedShort(final int offset) {
    method readShort (line 175) | public short readShort(final int offset) {
    method readInt (line 180) | public int readInt(final int offset) {
    method readLong (line 188) | public long readLong(final int offset) {
    method readUTF8 (line 194) | private String readUTF8(int cp_info_index) {
    method readUTF8 (line 200) | private String readUTF8(final int utfOffset, final int utfLength) {

FILE: src/main/java/lsieun/classfile/InsnRaw.java
  class InsnRaw (line 7) | public class InsnRaw {
    method InsnRaw (line 20) | public InsnRaw(byte[] code_bytes) {
    method getList (line 24) | @SuppressWarnings("Duplicates")
    method toNoArgIns (line 1563) | private String toNoArgIns(int offset, String mnemonic_symbol) {
    method toOneArgIns (line 1567) | private String toOneArgIns(int currentOffSet, String mnemonic_symbol, ...
    method toTwoArgIns (line 1571) | private String toTwoArgIns(int currentOffSet, String mnemonic_symbol, ...
    method visitCPIns (line 1575) | private String visitCPIns(int currentOffSet, String mnemonic_symbol, i...
    method readByte (line 1579) | public int readByte(final int offset) {
    method readUnsignedByte (line 1583) | public int readUnsignedByte(final int offset) {
    method readShort (line 1587) | public short readShort(final int offset) {
    method readUnsignedShort (line 1592) | public int readUnsignedShort(final int offset) {
    method readInt (line 1597) | public int readInt(final int offset) {
    method readLong (line 1605) | public long readLong(final int offset) {

FILE: src/main/java/lsieun/cst/Const.java
  class Const (line 3) | public class Const {

FILE: src/main/java/lsieun/drawing/canvas/Box.java
  type Box (line 11) | public enum Box {
    method Box (line 29) | Box(int flag, String val) {
    method merge (line 34) | public Box merge(Box another) {
    method merge (line 39) | public static Box merge(String val1, String val2) {
    method fromString (line 45) | public static Box fromString(String val) {
    method fromFlag (line 55) | public static Box fromFlag(int flag) {
    method isValid (line 65) | public static boolean isValid(String val) {

FILE: src/main/java/lsieun/drawing/canvas/Canvas.java
  class Canvas (line 10) | public class Canvas {
    method moveTo (line 16) | public Canvas moveTo(int row, int col) {
    method up (line 22) | public Canvas up(int count) {
    method down (line 27) | public Canvas down(int count) {
    method left (line 32) | public Canvas left(int count) {
    method right (line 37) | public Canvas right(int count) {
    method rectifyPosition (line 42) | public void rectifyPosition() {
    method updatePosition (line 62) | public void updatePosition(int startRow, int startCol) {
    method drawPixel (line 71) | public void drawPixel(Box value) {
    method drawPixel (line 88) | public void drawPixel(String value) {
    method switchDirection (line 101) | public Canvas switchDirection(TextDirection from, TextDirection to) {
    method drawHorizontalLine (line 143) | public Canvas drawHorizontalLine(int num) {
    method drawVerticalLine (line 153) | public Canvas drawVerticalLine(int num) {
    method drawText (line 163) | public void drawText(String text) {
    method drawRectangle (line 174) | public void drawRectangle(int width, int height) {
    method drawTable (line 208) | public void drawTable(int[] rowHeightArray, int[] colWidthArray) {
    method printPixels (line 255) | public void printPixels() {
    method getLines (line 265) | public List<String> getLines() {
    method toString (line 296) | @Override
    method draw (line 302) | public void draw(int row, int col, Drawable drawable) {
    method overlay (line 306) | public void overlay(Canvas canvas) {
    method findPixel (line 329) | private TextPixel findPixel(int row, int col) {
    method findMaxRow (line 338) | private int findMaxRow(List<TextPixel> list) {
    method findMaxCol (line 348) | private int findMaxCol(List<TextPixel> list) {
    method findRowItems (line 358) | private List<TextPixel> findRowItems(int row) {

FILE: src/main/java/lsieun/drawing/canvas/Drawable.java
  type Drawable (line 3) | public interface Drawable {
    method draw (line 4) | void draw(Canvas canvas, int startRow, int startCol);

FILE: src/main/java/lsieun/drawing/canvas/TextAlign.java
  type TextAlign (line 3) | public enum TextAlign {

FILE: src/main/java/lsieun/drawing/canvas/TextDirection.java
  type TextDirection (line 3) | public enum TextDirection {

FILE: src/main/java/lsieun/drawing/canvas/TextPixel.java
  class TextPixel (line 3) | public class TextPixel implements Comparable<TextPixel> {
    method TextPixel (line 8) | public TextPixel(int row, int col, String value) {
    method compareTo (line 14) | @Override
    method toString (line 31) | @Override
    method valueOf (line 36) | public static TextPixel valueOf(int row, int col, String value) {

FILE: src/main/java/lsieun/drawing/theme/line/ContinuousLine.java
  class ContinuousLine (line 8) | public class ContinuousLine implements Drawable {
    method setDirection (line 13) | public void setDirection(TextDirection direction) {
    method turn (line 17) | public ContinuousLine turn(TextDirection direction) {
    method drawLine (line 57) | public ContinuousLine drawLine(int count) {
    method draw (line 81) | @Override

FILE: src/main/java/lsieun/drawing/theme/shape/Rectangle.java
  class Rectangle (line 7) | public class Rectangle implements Drawable {
    method Rectangle (line 11) | public Rectangle(int width, int height) {
    method draw (line 16) | @SuppressWarnings({"UnnecessaryLocalVariable", "Duplicates"})

FILE: src/main/java/lsieun/drawing/theme/shape/RectangleWithText.java
  class RectangleWithText (line 9) | public class RectangleWithText extends Rectangle implements Drawable {
    method RectangleWithText (line 14) | public RectangleWithText(int width, int height, List<String> lines, Te...
    method draw (line 20) | @SuppressWarnings({"UnnecessaryLocalVariable"})

FILE: src/main/java/lsieun/drawing/theme/table/AbstractTable.java
  class AbstractTable (line 5) | public abstract class AbstractTable implements Drawable {
    method AbstractTable (line 8) | public AbstractTable() {
    method AbstractTable (line 12) | public AbstractTable(int cell_inner_padding) {
    method getCellLength (line 16) | protected abstract int getCellLength(int row, int col);
    method getColWidthArray (line 18) | public int[] getColWidthArray(int rowCount, int colCount) {

FILE: src/main/java/lsieun/drawing/theme/table/FixedWidthOneLineTable.java
  class FixedWidthOneLineTable (line 6) | public class FixedWidthOneLineTable extends OneLineTable implements Draw...
    method FixedWidthOneLineTable (line 9) | public FixedWidthOneLineTable(String[][] matrix, TextAlign align, int ...
    method getCellLength (line 14) | @Override

FILE: src/main/java/lsieun/drawing/theme/table/OneLineTable.java
  class OneLineTable (line 7) | public class OneLineTable extends AbstractTable implements Drawable {
    method OneLineTable (line 14) | public OneLineTable(String[][] matrix, TextAlign align) {
    method OneLineTable (line 18) | public OneLineTable(String[][] matrix, TextAlign align, int row_paddin...
    method getCellLength (line 25) | @Override
    method draw (line 32) | @Override

FILE: src/main/java/lsieun/drawing/theme/text/PlainText.java
  class PlainText (line 9) | public class PlainText implements Drawable {
    method draw (line 12) | @Override
    method valueOf (line 23) | public static PlainText valueOf(String line) {
    method valueOf (line 29) | public static PlainText valueOf(List<String> lines) {

FILE: src/main/java/lsieun/trove/HashFunctions.java
  class HashFunctions (line 3) | public final class HashFunctions {
    method hash (line 9) | public static int hash(double value) {
    method hash (line 22) | public static int hash(float value) {
    method hash (line 41) | public static int hash(int value) {
    method hash (line 61) | public static int hash(long value) {
    method hash (line 88) | public static int hash(Object object) {

FILE: src/main/java/lsieun/trove/PrimeFinder.java
  class PrimeFinder (line 5) | public final class PrimeFinder {
    method nextPrime (line 67) | public static int nextPrime(int desiredCapacity) {

FILE: src/main/java/lsieun/trove/THash.java
  class THash (line 3) | public abstract class THash implements Cloneable {
    method THash (line 49) | public THash() {
    method THash (line 60) | public THash(int initialCapacity) {
    method THash (line 73) | public THash(int initialCapacity, float loadFactor) {
    method clone (line 79) | @Override
    method isEmpty (line 93) | public boolean isEmpty() {
    method size (line 102) | public int size() {
    method capacity (line 109) | protected abstract int capacity();
    method ensureCapacity (line 119) | public void ensureCapacity(int desiredCapacity) {
    method compact (line 143) | public void compact() {
    method trimToSize (line 158) | public final void trimToSize() {
    method removeAt (line 168) | protected void removeAt(int index) {
    method compactIfNecessary (line 175) | private void compactIfNecessary() {
    method stopCompactingOnRemove (line 182) | public final void stopCompactingOnRemove() {
    method startCompactingOnRemove (line 190) | public final void startCompactingOnRemove(boolean compact) {
    method clear (line 204) | public void clear() {
    method setUp (line 217) | protected int setUp(int initialCapacity) {
    method rehash (line 228) | protected abstract void rehash(int newCapacity);
    method computeMaxSize (line 236) | private void computeMaxSize(int capacity) {
    method postInsertHook (line 247) | protected final void postInsertHook(boolean usedFreeSlot) {
    method calculateGrownCapacity (line 262) | protected int calculateGrownCapacity() {

FILE: src/main/java/lsieun/trove/TIntArrayList.java
  class TIntArrayList (line 14) | public class TIntArrayList implements Serializable, Cloneable {
    method TIntArrayList (line 35) | public TIntArrayList() {
    method TIntArrayList (line 44) | public TIntArrayList(int capacity) {
    method TIntArrayList (line 57) | public TIntArrayList(int[] values) {
    method ensureCapacity (line 72) | public void ensureCapacity(int capacity) {
    method size (line 89) | public int size() {
    method isEmpty (line 98) | public boolean isEmpty() {
    method trimToSize (line 106) | public void trimToSize() {
    method add (line 121) | public void add(int val) {
    method add (line 132) | public void add(int[] vals) {
    method add (line 144) | public void add(int[] vals, int offset, int length) {
    method insert (line 158) | public void insert(int offset, int value) {
    method insert (line 179) | public void insert(int offset, int[] values) {
    method insert (line 194) | public void insert(int offset, int[] values, int valOffset, int len) {
    method get (line 214) | public int get(int offset) {
    method getQuick (line 228) | public int getQuick(int offset) {
    method set (line 238) | public void set(int offset, int val) {
    method getSet (line 253) | public int getSet(int offset, int val) {
    method set (line 269) | public void set(int offset, int[] values) {
    method set (line 283) | public void set(int offset, int[] values, int valOffset, int length) {
    method setQuick (line 297) | public void setQuick(int offset, int val) {
    method clear (line 305) | public void clear() {
    method clear (line 316) | public void clear(int capacity) {
    method reset (line 329) | public void reset() {
    method resetQuick (line 348) | public void resetQuick() {
    method remove (line 358) | public int remove(int offset) {
    method remove (line 371) | public void remove(int offset, int length) {
    method transformValues (line 400) | public void transformValues(TIntFunction function) {
    method reverse (line 409) | public void reverse() {
    method reverse (line 419) | public void reverse(int from, int to) {
    method shuffle (line 437) | public void shuffle(Random rand) {
    method swap (line 449) | private void swap(int i, int j) {
    method clone (line 463) | @Override
    method toNativeArray (line 481) | public int[] toNativeArray() {
    method toNativeArray (line 492) | public int[] toNativeArray(int offset, int len) {
    method toNativeArray (line 505) | public void toNativeArray(int[] dest, int offset, int len) {
    method equals (line 524) | @Override
    method hashCode (line 548) | @Override
    method forEach (line 566) | public boolean forEach(TIntProcedure procedure) {
    method forEachDescending (line 582) | public boolean forEachDescending(TIntProcedure procedure) {
    method sort (line 599) | public void sort() {
    method sort (line 611) | public void sort(int fromIndex, int toIndex) {
    method fill (line 622) | public void fill(int val) {
    method fill (line 633) | public void fill(int fromIndex, int toIndex, int val) {
    method binarySearch (line 652) | public int binarySearch(int value) {
    method binarySearch (line 667) | public int binarySearch(int value, int fromIndex, int toIndex) {
    method indexOf (line 704) | public int indexOf(int value) {
    method indexOf (line 719) | public int indexOf(int offset, int value) {
    method lastIndexOf (line 737) | public int lastIndexOf(int value) {
    method lastIndexOf (line 752) | public int lastIndexOf(int offset, int value) {
    method contains (line 767) | public boolean contains(int value) {
    method grep (line 778) | public TIntArrayList grep(TIntProcedure condition) {
    method inverseGrep (line 795) | public TIntArrayList inverseGrep(TIntProcedure condition) {
    method max (line 811) | public int max() {
    method min (line 828) | public int min() {
    method toString (line 846) | @Override

FILE: src/main/java/lsieun/trove/TIntFunction.java
  type TIntFunction (line 11) | public interface TIntFunction {
    method execute (line 18) | int execute(int value);

FILE: src/main/java/lsieun/trove/TIntHash.java
  class TIntHash (line 3) | public abstract class TIntHash extends TPrimitiveHash
    method TIntHash (line 16) | public TIntHash() {
    method TIntHash (line 27) | public TIntHash(int initialCapacity) {
    method TIntHash (line 40) | public TIntHash(int initialCapacity, float loadFactor) {
    method TIntHash (line 50) | public TIntHash(TIntHashingStrategy strategy) {
    method TIntHash (line 62) | public TIntHash(int initialCapacity, TIntHashingStrategy strategy) {
    method TIntHash (line 76) | public TIntHash(int initialCapacity, float loadFactor, TIntHashingStra...
    method clone (line 84) | @Override
    method setUp (line 98) | @Override
    method contains (line 111) | public boolean contains(int val) {
    method forEach (line 122) | public boolean forEach(TIntProcedure procedure) {
    method removeAt (line 140) | @Override
    method index (line 152) | protected int index(int val) {
    method insertionIndex (line 185) | protected int insertionIndex(int val) {
    method computeHashCode (line 237) | public final int computeHashCode(int val) {

FILE: src/main/java/lsieun/trove/TIntHashingStrategy.java
  type TIntHashingStrategy (line 14) | public interface TIntHashingStrategy extends Serializable {
    method computeHashCode (line 23) | int computeHashCode(int val);

FILE: src/main/java/lsieun/trove/TIntIntHashMap.java
  class TIntIntHashMap (line 3) | public class TIntIntHashMap extends TIntHash {
    method TIntIntHashMap (line 14) | public TIntIntHashMap() {
    method TIntIntHashMap (line 24) | public TIntIntHashMap(int initialCapacity) {
    method TIntIntHashMap (line 36) | public TIntIntHashMap(int initialCapacity, float loadFactor) {
    method TIntIntHashMap (line 46) | public TIntIntHashMap(TIntHashingStrategy strategy) {
    method TIntIntHashMap (line 58) | public TIntIntHashMap(int initialCapacity, TIntHashingStrategy strateg...
    method TIntIntHashMap (line 71) | public TIntIntHashMap(int initialCapacity, float loadFactor, TIntHashi...
    method clone (line 78) | @Override
    method iterator (line 88) | public TIntIntIterator iterator() {
    method setUp (line 99) | @Override
    method put (line 114) | public int put(int key, int value) {
    method rehash (line 139) | @Override
    method get (line 167) | public int get(int key) {
    method clear (line 175) | @Override
    method remove (line 196) | public int remove(int key) {
    method equals (line 213) | @Override
    method hashCode (line 225) | @Override
    class HashProcedure (line 232) | private final class HashProcedure implements TIntIntProcedure {
      method HashProcedure (line 235) | HashProcedure() {
      method getHashCode (line 238) | public int getHashCode() {
      method execute (line 242) | public final boolean execute(int key, int value) {
    class EqProcedure (line 248) | private static final class EqProcedure implements TIntIntProcedure {
      method EqProcedure (line 251) | EqProcedure(TIntIntHashMap otherMap) {
      method execute (line 255) | public final boolean execute(int key, int value) {
      method eq (line 263) | private static boolean eq(int v1, int v2) {
    method removeAt (line 274) | @Override
    method getValues (line 285) | public int[] getValues() {
    method keys (line 305) | public int[] keys() {
    method containsValue (line 326) | public boolean containsValue(int val) {
    method containsKey (line 346) | public boolean containsKey(int key) {
    method forEachKey (line 357) | public boolean forEachKey(TIntProcedure procedure) {
    method forEachValue (line 368) | public boolean forEachValue(TIntProcedure procedure) {
    method forEachEntry (line 389) | public boolean forEachEntry(TIntIntProcedure procedure) {
    method retainEntries (line 410) | public boolean retainEntries(TIntIntProcedure procedure) {
    method transformValues (line 431) | public void transformValues(TIntFunction function) {
    method increment (line 449) | public boolean increment(int key) {
    method adjustValue (line 460) | public boolean adjustValue(int key, int amount) {
    method toString (line 471) | @Override

FILE: src/main/java/lsieun/trove/TIntIntIterator.java
  class TIntIntIterator (line 3) | public class TIntIntIterator extends TPrimitiveIterator {
    method TIntIntIterator (line 12) | public TIntIntIterator(TIntIntHashMap map) {
    method advance (line 23) | public void advance() {
    method key (line 34) | public int key() {
    method value (line 45) | public int value() {
    method setValue (line 57) | public int setValue(int val) {

FILE: src/main/java/lsieun/trove/TIntIntProcedure.java
  type TIntIntProcedure (line 3) | public interface TIntIntProcedure {
    method execute (line 15) | boolean execute(int a, int b);

FILE: src/main/java/lsieun/trove/TIntProcedure.java
  type TIntProcedure (line 3) | public interface TIntProcedure {
    method execute (line 13) | boolean execute(int value);

FILE: src/main/java/lsieun/trove/TIterator.java
  class TIterator (line 14) | abstract class TIterator {
    method TIterator (line 26) | public TIterator(THash hash) {
    method hasNext (line 38) | public boolean hasNext() {
    method remove (line 48) | public void remove() {
    method moveToNextIndex (line 67) | protected final void moveToNextIndex() {
    method nextIndex (line 81) | protected abstract int nextIndex();

FILE: src/main/java/lsieun/trove/TPrimitiveHash.java
  class TPrimitiveHash (line 3) | public abstract class TPrimitiveHash extends THash {
    method TPrimitiveHash (line 24) | public TPrimitiveHash() {
    method TPrimitiveHash (line 35) | public TPrimitiveHash(int initialCapacity) {
    method TPrimitiveHash (line 48) | public TPrimitiveHash(int initialCapacity, float loadFactor) {
    method clone (line 52) | @Override
    method capacity (line 65) | @Override
    method removeAt (line 75) | @Override
    method setUp (line 88) | @Override

FILE: src/main/java/lsieun/trove/TPrimitiveIterator.java
  class TPrimitiveIterator (line 26) | abstract class TPrimitiveIterator extends TIterator {
    method TPrimitiveIterator (line 33) | public TPrimitiveIterator(TPrimitiveHash hash) {
    method nextIndex (line 46) | @Override

FILE: src/main/java/lsieun/utils/ASMUtilsCore.java
  class ASMUtilsCore (line 5) | public class ASMUtilsCore {
    method read (line 6) | public int read(ClassReader cr, int off, char[] buf,
    method getMethodOffset (line 15) | public static int getMethodOffset(ClassReader cr, int codeOff, char[] ...
    method swap (line 51) | public static void swap(MethodVisitor mv, Type stackTop, Type belowTop) {

FILE: src/main/java/lsieun/utils/ASMUtilsTree.java
  class ASMUtilsTree (line 6) | public class ASMUtilsTree {
    method getVariableName (line 9) | public static String getVariableName(String className, MethodNode mn, ...
    method findLineLabel (line 26) | public static LabelNode findLineLabel(InsnList instructions, int line) {
    method findMethodCall (line 38) | public static int findMethodCall(InsnList instructions, LabelNode labe...

FILE: src/main/java/lsieun/utils/BoxDrawingUtils.java
  class BoxDrawingUtils (line 14) | public class BoxDrawingUtils {
    method printInstructionLinks (line 17) | public static void printInstructionLinks(InsnList instructions, int[] ...
    method contains (line 105) | private static boolean contains(int[] array, int val) {
    method printTable (line 114) | public static void printTable(String[][] matrix) {

FILE: src/main/java/lsieun/utils/ByteArrayClassLoader.java
  class ByteArrayClassLoader (line 6) | public class ByteArrayClassLoader extends ClassLoader {
    method defineClass (line 7) | public final Class<?> defineClass(byte[] bytes) {
    method defineClass (line 14) | public Class<?> defineClass(String name, byte[] bytes) {

FILE: src/main/java/lsieun/utils/ByteUtils.java
  class ByteUtils (line 7) | public class ByteUtils {
    method intToByteArray (line 8) | public static byte[] intToByteArray(int value) {
    method merge (line 14) | public static byte[] merge(byte[]... bytesArray) {
    method concatenate (line 32) | public static byte[] concatenate(byte[] bytes1, byte[] bytes2) {
    method concatenate (line 44) | public static byte[] concatenate(byte[] bytes1, byte[] bytes2, byte[] ...

FILE: src/main/java/lsieun/utils/DescriptorUtils.java
  class DescriptorUtils (line 3) | public class DescriptorUtils {
    method simplify (line 4) | public static String simplify(String descriptor) {

FILE: src/main/java/lsieun/utils/FileUtils.java
  class FileUtils (line 10) | public class FileUtils {
    method getFilePath (line 11) | public static String getFilePath(String relativePath) {
    method getFilePath (line 16) | public static String getFilePath(Class<?> clazz, String className) {
    method readBytes (line 21) | public static byte[] readBytes(String filepath) {
    method writeBytes (line 48) | public static void writeBytes(String filepath, byte[] bytes) {
    method readLines (line 65) | public static List<String> readLines(String filepath) {
    method readLines (line 69) | public static List<String> readLines(String filepath, String charsetNa...
    method writeLines (line 105) | public static void writeLines(String filepath, List<String> lines) {
    method mkdirs (line 136) | public static void mkdirs(File dirFile) {
    method clear (line 153) | public static void clear(File file) {
    method delete (line 171) | public static void delete(File file) {
    method readStream (line 194) | public static byte[] readStream(final InputStream in, final boolean cl...
    method getInputStream (line 215) | public static InputStream getInputStream(String className) {

FILE: src/main/java/lsieun/utils/FrameUtils.java
  class FrameUtils (line 18) | public class FrameUtils {
    method printFrames (line 24) | public static <V extends Value, T> void printFrames(String owner, Meth...
    method getFrameLine (line 58) | public static <V extends Value, T> String getFrameLine(Frame<V> f, Fun...
    method toLine (line 88) | public static <T> String toLine(List<T> localList, List<T> stackList) {
    method toLine (line 94) | private static <T> String toLine(List<T> list) {
    method printGraph (line 109) | public static <V extends Value, T> void printGraph(String owner, Metho...
    method printOneFrame (line 148) | public static <V extends Value, T> void printOneFrame(int maxLocals, i...

FILE: src/main/java/lsieun/utils/HexFormat.java
  type HexFormat (line 3) | public enum HexFormat {
    method HexFormat (line 23) | HexFormat(String separator, int columns) {

FILE: src/main/java/lsieun/utils/HexUtils.java
  class HexUtils (line 5) | public class HexUtils {
    method format (line 7) | public static String format(byte[] bytes, HexFormat format) {
    method format (line 13) | public static String format(byte[] bytes, String separator, int bytes_...
    method parse (line 37) | public static byte[] parse(String str, HexFormat format) {
    method parse (line 42) | public static byte[] parse(String str, char[] chars) {
    method is_in (line 57) | public static boolean is_in(char ch, char[] chars) {
    method parse (line 66) | public static byte[] parse(String hex_str) {
    method toHex (line 79) | public static String toHex(byte[] bytes) {

FILE: src/main/java/lsieun/utils/IOUtils.java
  class IOUtils (line 10) | public class IOUtils {
    method copy (line 15) | public static int copy(final InputStream input, final OutputStream out...
    method copyLarge (line 23) | public static long copyLarge(final InputStream input, final OutputStre...
    method copy (line 28) | public static long copy(final InputStream input, final OutputStream ou...
    method copyLarge (line 33) | public static long copyLarge(final InputStream input, final OutputStre...
    method copyLarge (line 44) | public static long copyLarge(final Reader input, final Writer output) ...
    method copyLarge (line 48) | public static long copyLarge(final Reader input, final Writer output, ...
    method closeQuietly (line 58) | public static void closeQuietly(final Closeable closeable) {

FILE: src/main/java/lsieun/utils/JarUtils.java
  class JarUtils (line 11) | public class JarUtils {
    method getAllEntries (line 14) | public static List<String> getAllEntries(String filePath) {
    method getClassEntries (line 30) | public static List<String> getClassEntries(String filepath) {
    method readClass (line 43) | public static byte[] readClass(String jarPath, String entryName) {
    method getAllEntryMap (line 58) | public static Map<String, ByteArrayOutputStream> getAllEntryMap(String...

FILE: src/main/java/lsieun/utils/OpcodeConst.java
  class OpcodeConst (line 3) | public class OpcodeConst {
    method getOpcodeName (line 72) | public static String getOpcodeName(final int index) {
    method getNoOfOperands (line 144) | public static short getNoOfOperands(final int index) {

FILE: src/main/java/lsieun/utils/ReadUtils.java
  class ReadUtils (line 7) | public class ReadUtils {
    method readByPath (line 12) | public static byte[] readByPath(String filepath) {
    method readByProject (line 21) | public static byte[] readByProject(String class_name) {
    method readByClassLoader (line 32) | public static byte[] readByClassLoader(Class<?> clazz) {
    method readByJar (line 44) | public static byte[] readByJar(String jar_path, String entry_name) {

FILE: src/main/java/lsieun/utils/StringUtils.java
  class StringUtils (line 6) | public class StringUtils {
    method array2Bytes (line 7) | public static byte[] array2Bytes(String str) {
    method list2str (line 18) | public static String list2str(List<String> list) {

FILE: src/main/java/lsieun/utils/ValueUtils.java
  class ValueUtils (line 14) | public class ValueUtils {
    method fromBasicValue2String (line 15) | public static String fromBasicValue2String(BasicValue basicValue) {
    method fromSourceValue2String (line 20) | public static String fromSourceValue2String(MethodNode mn, SourceValue...
    method fromSourceValue2Index (line 32) | public static String fromSourceValue2Index(MethodNode mn, SourceValue ...
    method fromNullabilityValue2String (line 44) | public static String fromNullabilityValue2String(NullabilityValue valu...

FILE: src/main/java/run/ASMPrint.java
  class ASMPrint (line 23) | public class ASMPrint {
    method main (line 24) | public static void main(String[] args) throws IOException {

FILE: src/main/java/run/BoxDrawingRun.java
  class BoxDrawingRun (line 5) | public class BoxDrawingRun {
    method main (line 28) | public static void main(String[] args) {

FILE: src/main/java/run/BytecodeRun.java
  class BytecodeRun (line 9) | public class BytecodeRun {
    method main (line 10) | public static void main(String[] args) {

FILE: src/main/java/run/ControlFlowGraphRun.java
  class ControlFlowGraphRun (line 17) | public class ControlFlowGraphRun {
    method main (line 18) | public static void main(String[] args) throws Exception {
    method display (line 58) | private static void display(String owner, MethodNode mn, ControlFlowGr...

FILE: src/main/java/run/ControlFlowGraphType.java
  type ControlFlowGraphType (line 3) | public enum ControlFlowGraphType {

FILE: src/main/java/run/HelloWorldAnalysisCore.java
  class HelloWorldAnalysisCore (line 9) | public class HelloWorldAnalysisCore {
    method main (line 10) | public static void main(String[] args) {

FILE: src/main/java/run/HelloWorldAnalysisTree.java
  class HelloWorldAnalysisTree (line 12) | public class HelloWorldAnalysisTree {
    method main (line 13) | public static void main(String[] args) throws Exception {

FILE: src/main/java/run/HelloWorldFrameCore.java
  class HelloWorldFrameCore (line 9) | public class HelloWorldFrameCore {
    method main (line 10) | public static void main(String[] args) {

FILE: src/main/java/run/HelloWorldFrameCore02.java
  class HelloWorldFrameCore02 (line 9) | public class HelloWorldFrameCore02 {
    method main (line 10) | public static void main(String[] args) {

FILE: src/main/java/run/HelloWorldFrameTree.java
  class HelloWorldFrameTree (line 19) | public class HelloWorldFrameTree {
    method main (line 20) | public static void main(String[] args) throws Exception {
    method print (line 40) | private static void print(String owner, MethodNode mn, int option) thr...
    method print (line 108) | public static <V extends Value, T> void print(String owner, MethodNode...

FILE: src/main/java/run/HelloWorldGenerateCore.java
  class HelloWorldGenerateCore (line 8) | public class HelloWorldGenerateCore {
    method main (line 9) | public static void main(String[] args) throws Exception {
    method dump (line 20) | public static byte[] dump() throws Exception {

FILE: src/main/java/run/HelloWorldGenerateTree.java
  class HelloWorldGenerateTree (line 9) | public class HelloWorldGenerateTree {
    method main (line 10) | public static void main(String[] args) throws Exception {
    method dump (line 21) | public static byte[] dump() throws Exception {

FILE: src/main/java/run/HelloWorldRun.java
  class HelloWorldRun (line 3) | public class HelloWorldRun {
    method main (line 4) | public static void main(String[] args) throws Exception {

FILE: src/main/java/run/HelloWorldTransformCore.java
  class HelloWorldTransformCore (line 8) | public class HelloWorldTransformCore {
    method main (line 9) | public static void main(String[] args) {

FILE: src/main/java/run/HelloWorldTransformTree.java
  class HelloWorldTransformTree (line 11) | public class HelloWorldTransformTree {
    method main (line 12) | public static void main(String[] args) {

FILE: src/main/java/run/MockAnalyzerRun.java
  class MockAnalyzerRun (line 14) | public class MockAnalyzerRun {
    method main (line 15) | public static void main(String[] args) throws Exception {

FILE: src/main/java/run/PrintASMCodeCore.java
  class PrintASMCodeCore (line 19) | public class PrintASMCodeCore {
    method main (line 20) | public static void main(String[] args) throws IOException {

FILE: src/main/java/run/PrintASMCodeTree.java
  class PrintASMCodeTree (line 19) | public class PrintASMCodeTree {
    method main (line 20) | public static void main(String[] args) throws IOException {

FILE: src/main/java/run/PrintASMTextClass.java
  class PrintASMTextClass (line 17) | public class PrintASMTextClass {
    method main (line 18) | public static void main(String[] args) throws IOException {

FILE: src/main/java/run/PrintASMTextLambda.java
  class PrintASMTextLambda (line 20) | public class PrintASMTextLambda {
    method main (line 21) | public static void main(String[] args) throws IOException {

FILE: src/main/java/run/PrintOpcodeTable.java
  class PrintOpcodeTable (line 8) | public class PrintOpcodeTable {
    method main (line 12) | public static void main(String[] args) throws Exception {
    method printOpcode (line 16) | public static void printOpcode() {
    method getOpcodeName (line 47) | public static String getOpcodeName(int i) {

FILE: src/main/java/run/jar/CompareTwoJarFile.java
  class CompareTwoJarFile (line 15) | public class CompareTwoJarFile {
    method main (line 17) | public static void main(String[] args) {
    method generateOtherFile (line 65) | public static void generateOtherFile(byte[] bytes, String item, String...
    method generateClassText (line 86) | public static void generateClassText(byte[] bytes, String suffix) {

FILE: src/main/java/run/jar/FindJarClassItem.java
  class FindJarClassItem (line 12) | public class FindJarClassItem {
    method main (line 13) | public static void main(String[] args) {

FILE: src/main/java/sample/HelloWorld.java
  class HelloWorld (line 5) | public class HelloWorld {
    method main (line 6) | public static void main(String[] args) {

FILE: src/main/java/sample/ParameterUtils.java
  class ParameterUtils (line 8) | public class ParameterUtils {
    method printValueOnStack (line 13) | public static void printValueOnStack(boolean value) {
    method printValueOnStack (line 17) | public static void printValueOnStack(byte value) {
    method printValueOnStack (line 21) | public static void printValueOnStack(char value) {
    method printValueOnStack (line 25) | public static void printValueOnStack(short value) {
    method printValueOnStack (line 29) | public static void printValueOnStack(int value) {
    method printValueOnStack (line 33) | public static void printValueOnStack(float value) {
    method printValueOnStack (line 37) | public static void printValueOnStack(long value) {
    method printValueOnStack (line 41) | public static void printValueOnStack(double value) {
    method printValueOnStack (line 45) | public static void printValueOnStack(Object value) {
    method printText (line 59) | public static void printText(String str) {
    method output (line 63) | public static void output(PrintStream printStream, int val) {
Condensed preview — 231 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (685K chars).
[
  {
    "path": ".gitignore",
    "chars": 364,
    "preview": "# Compiled class file\n*.class\n\n# Log file\n*.log\n\n# BlueJ files\n*.ctxt\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Packa"
  },
  {
    "path": "LICENSE",
    "chars": 1063,
    "preview": "MIT License\n\nCopyright (c) 2020 lsieun\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof "
  },
  {
    "path": "README.md",
    "chars": 9611,
    "preview": "# Learn Java ASM\n\n[![Gitee](https://img.shields.io/badge/Gitee-white.svg?style=flat-square&logo=gitee&logoColor=C71D23)]"
  },
  {
    "path": "accepted-words.dic",
    "chars": 27,
    "preview": "bilibili\ngitee\ninsn\nlsieun\n"
  },
  {
    "path": "pom.xml",
    "chars": 3075,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www"
  },
  {
    "path": "src/main/java/lsieun/annotation/todo/ToDo.java",
    "chars": 540,
    "preview": "package lsieun.annotation.todo;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimp"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/ControlFlowAnalyzer.java",
    "chars": 7184,
    "preview": "package lsieun.asm.analysis;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.*;\nimport org.objectweb.as"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/ControlFlowAnalyzer2.java",
    "chars": 3093,
    "preview": "package lsieun.asm.analysis;\n\nimport lsieun.asm.analysis.graph.InsnBlock;\nimport org.objectweb.asm.tree.AbstractInsnNode"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/ControlFlowEdgeAnalyzer.java",
    "chars": 3160,
    "preview": "package lsieun.asm.analysis;\n\nimport lsieun.asm.analysis.graph.InsnBlock;\nimport org.objectweb.asm.tree.AbstractInsnNode"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/ControlFlowEdgeAnalyzer2.java",
    "chars": 2530,
    "preview": "package lsieun.asm.analysis;\n\nimport lsieun.asm.analysis.graph.InsnBlock;\nimport org.objectweb.asm.tree.analysis.Interpr"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/ControlFlowGraphAnalyzer.java",
    "chars": 6684,
    "preview": "package lsieun.asm.analysis;\n\nimport lsieun.asm.analysis.graph.InsnBlock;\nimport org.objectweb.asm.tree.*;\n\nimport java."
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/DataFlowAnalyzer.java",
    "chars": 11179,
    "preview": "package lsieun.asm.analysis;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm."
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/InsnText.java",
    "chars": 10404,
    "preview": "package lsieun.asm.analysis;\n\nimport lsieun.utils.OpcodeConst;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.t"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/MockAnalyzer.java",
    "chars": 7767,
    "preview": "package lsieun.asm.analysis;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm."
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/RemoveDeadCodeNode.java",
    "chars": 1963,
    "preview": "package lsieun.asm.analysis;\n\nimport lsieun.asm.tree.transformer.MethodTransformer;\nimport org.objectweb.asm.ClassVisito"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/RemoveDeadCodeVisitor.java",
    "chars": 2477,
    "preview": "package lsieun.asm.analysis;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org."
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/RemoveUnusedCastNode.java",
    "chars": 3128,
    "preview": "package lsieun.asm.analysis;\n\nimport lsieun.asm.tree.transformer.MethodTransformer;\nimport org.objectweb.asm.ClassVisito"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/RemoveUnusedCastVisitor.java",
    "chars": 2624,
    "preview": "package lsieun.asm.analysis;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org."
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/cc/CyclomaticComplexity.java",
    "chars": 783,
    "preview": "package lsieun.asm.analysis.cc;\n\nimport org.objectweb.asm.tree.MethodNode;\nimport org.objectweb.asm.tree.analysis.*;\n\npu"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/cc/CyclomaticComplexityAnalyzer.java",
    "chars": 838,
    "preview": "package lsieun.asm.analysis.cc;\n\nimport org.objectweb.asm.tree.analysis.*;\n\npublic class CyclomaticComplexityAnalyzer<V "
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/cc/CyclomaticComplexityFrame.java",
    "chars": 532,
    "preview": "package lsieun.asm.analysis.cc;\n\nimport org.objectweb.asm.tree.analysis.Frame;\nimport org.objectweb.asm.tree.analysis.Va"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/cfg/ControlFlowBuilder.java",
    "chars": 1300,
    "preview": "package lsieun.asm.analysis.cfg;\n\nimport org.objectweb.asm.tree.MethodNode;\nimport org.objectweb.asm.tree.analysis.Analy"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/cfg/ControlFlowGraph.java",
    "chars": 1114,
    "preview": "package lsieun.asm.analysis.cfg;\n\nimport java.util.Arrays;\nimport java.util.Formatter;\n\npublic final class ControlFlowGr"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/cfg/Edge.java",
    "chars": 544,
    "preview": "package lsieun.asm.analysis.cfg;\n\npublic final class Edge {\n    public final int from;\n    public final int to;\n\n    pub"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/cfg/EdgeCreator.java",
    "chars": 197,
    "preview": "package lsieun.asm.analysis.cfg;\n\npublic interface EdgeCreator {\n    void newControlFlowEdge(int insn, int successor);\n\n"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/cfg/FramelessAnalyzer.java",
    "chars": 6620,
    "preview": "package lsieun.asm.analysis.cfg;\n\nimport org.objectweb.asm.tree.*;\nimport org.objectweb.asm.tree.analysis.AnalyzerExcept"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/cfg/SimpleEdgeCreator.java",
    "chars": 980,
    "preview": "package lsieun.asm.analysis.cfg;\n\nimport lsieun.trove.TIntArrayList;\n\npublic class SimpleEdgeCreator implements EdgeCrea"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/diagnosis/DeadCodeDiagnosis.java",
    "chars": 1260,
    "preview": "package lsieun.asm.analysis.diagnosis;\n\nimport lsieun.asm.analysis.ControlFlowAnalyzer;\nimport lsieun.trove.TIntArrayLis"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/diagnosis/NullDereferenceDiagnosis.java",
    "chars": 2372,
    "preview": "package lsieun.asm.analysis.diagnosis;\n\nimport lsieun.asm.analysis.nullability.NullDeferenceInterpreter;\nimport lsieun.t"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/diagnosis/NullabilityDiagnosis.java",
    "chars": 2777,
    "preview": "package lsieun.asm.analysis.diagnosis;\n\nimport lsieun.asm.analysis.nullability.Nullability;\nimport lsieun.asm.analysis.n"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/diagnosis/RedundantVariableDiagnosis.java",
    "chars": 2438,
    "preview": "package lsieun.asm.analysis.diagnosis;\n\nimport lsieun.trove.TIntArrayList;\nimport org.objectweb.asm.Opcodes;\nimport org."
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/diagnosis/RelatedInstructionDiagnosis.java",
    "chars": 3562,
    "preview": "package lsieun.asm.analysis.diagnosis;\n\nimport lsieun.asm.analysis.transition.DestinationInterpreter;\nimport lsieun.trov"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/diagnosis/ReverseEngineerMethodArgumentsDiagnosis.java",
    "chars": 3526,
    "preview": "package lsieun.asm.analysis.diagnosis;\n\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.*;\nimport org.objec"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/graph/InsnBlock.java",
    "chars": 697,
    "preview": "package lsieun.asm.analysis.graph;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class InsnBlock {\n    // "
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/graph/TextBox.java",
    "chars": 482,
    "preview": "package lsieun.asm.analysis.graph;\n\npublic class TextBox {\n    public final int row;\n    public final int col;\n    publi"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/graph/TextGraph.java",
    "chars": 5432,
    "preview": "package lsieun.asm.analysis.graph;\n\nimport lsieun.drawing.canvas.Box;\nimport lsieun.drawing.canvas.Canvas;\nimport lsieun"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/nullability/NullDeferenceInterpreter.java",
    "chars": 1288,
    "preview": "package lsieun.asm.analysis.nullability;\n\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.AbstractInsnNode;"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/nullability/Nullability.java",
    "chars": 773,
    "preview": "package lsieun.asm.analysis.nullability;\n\npublic enum Nullability {\n    UNKNOWN(0),\n    NOT_NULL(1),\n    NULL(1),\n    NU"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/nullability/NullabilityAnalyzer.java",
    "chars": 703,
    "preview": "package lsieun.asm.analysis.nullability;\n\nimport org.objectweb.asm.tree.analysis.Analyzer;\nimport org.objectweb.asm.tree"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/nullability/NullabilityFrame.java",
    "chars": 1995,
    "preview": "package lsieun.asm.analysis.nullability;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.LabelNode;\nimp"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/nullability/NullabilityInterpreter.java",
    "chars": 16195,
    "preview": "package lsieun.asm.analysis.nullability;\n\nimport org.objectweb.asm.ConstantDynamic;\nimport org.objectweb.asm.Handle;\nimp"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/nullability/NullabilityValue.java",
    "chars": 1555,
    "preview": "package lsieun.asm.analysis.nullability;\n\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.analysis.Value;\n\n"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/state/StateInterpreter.java",
    "chars": 1881,
    "preview": "package lsieun.asm.analysis.state;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.objectwe"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/state/StateType.java",
    "chars": 197,
    "preview": "package lsieun.asm.analysis.state;\n\npublic enum StateType {\n    DEFAULT, // default\n    TOP,\n    INT,\n    FLOAT,\n    LON"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/state/StateValue.java",
    "chars": 291,
    "preview": "package lsieun.asm.analysis.state;\n\nimport org.objectweb.asm.tree.analysis.Value;\n\npublic class StateValue implements Va"
  },
  {
    "path": "src/main/java/lsieun/asm/analysis/transition/DestinationInterpreter.java",
    "chars": 4953,
    "preview": "package lsieun.asm.analysis.transition;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.obj"
  },
  {
    "path": "src/main/java/lsieun/asm/commons/ClassRemapperExample01.java",
    "chars": 1477,
    "preview": "package lsieun.asm.commons;\n\nimport lsieun.utils.FileUtils;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.a"
  },
  {
    "path": "src/main/java/lsieun/asm/commons/ClassRemapperExample02.java",
    "chars": 1712,
    "preview": "package lsieun.asm.commons;\n\nimport lsieun.utils.FileUtils;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.a"
  },
  {
    "path": "src/main/java/lsieun/asm/commons/ClassRemapperExample03.java",
    "chars": 1918,
    "preview": "package lsieun.asm.commons;\n\nimport lsieun.utils.FileUtils;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.a"
  },
  {
    "path": "src/main/java/lsieun/asm/commons/GeneratorAdapterExample01.java",
    "chars": 1963,
    "preview": "package lsieun.asm.commons;\n\nimport lsieun.utils.FileUtils;\nimport org.objectweb.asm.ClassWriter;\nimport org.objectweb.a"
  },
  {
    "path": "src/main/java/lsieun/asm/commons/InstructionAdapterExample01.java",
    "chars": 1977,
    "preview": "package lsieun.asm.commons;\n\nimport lsieun.utils.FileUtils;\nimport org.objectweb.asm.ClassWriter;\nimport org.objectweb.a"
  },
  {
    "path": "src/main/java/lsieun/asm/commons/MethodStackMapFrame02Visitor.java",
    "chars": 10459,
    "preview": "package lsieun.asm.commons;\n\nimport lsieun.classfile.ClassFile;\nimport lsieun.classfile.InsnRaw;\nimport org.objectweb.as"
  },
  {
    "path": "src/main/java/lsieun/asm/commons/MethodStackMapFrameVisitor.java",
    "chars": 6014,
    "preview": "package lsieun.asm.commons;\n\nimport org.objectweb.asm.*;\nimport org.objectweb.asm.commons.AnalyzerAdapter;\n\nimport java."
  },
  {
    "path": "src/main/java/lsieun/asm/commons/SerialVersionUIDAdderExample01.java",
    "chars": 1109,
    "preview": "package lsieun.asm.commons;\n\nimport lsieun.utils.FileUtils;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.a"
  },
  {
    "path": "src/main/java/lsieun/asm/commons/StaticInitMergerExample01.java",
    "chars": 3978,
    "preview": "package lsieun.asm.commons;\n\nimport lsieun.asm.template.ClassAddInterfaceVisitor;\nimport lsieun.asm.template.ClassMergeV"
  },
  {
    "path": "src/main/java/lsieun/asm/core/ChangeURLVisitor.java",
    "chars": 1945,
    "preview": "package lsieun.asm.core;\n\nimport lsieun.annotation.todo.ToDo;\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectwe"
  },
  {
    "path": "src/main/java/lsieun/asm/core/ClassChangeVersionVisitor.java",
    "chars": 502,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.Opcodes;\n\npublic class ClassCh"
  },
  {
    "path": "src/main/java/lsieun/asm/core/ClassCloneVisitor.java",
    "chars": 452,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\n\npublic class ClassCloneVisitor extends ClassVisitor {\n"
  },
  {
    "path": "src/main/java/lsieun/asm/core/ClassDecompileVisitor.java",
    "chars": 921,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.*;\n\npublic class ClassDecompileVisitor extends ClassVisitor {\n\n    pu"
  },
  {
    "path": "src/main/java/lsieun/asm/core/ClassListMemberVisitor.java",
    "chars": 1301,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.FieldVisitor;\nimport org.objec"
  },
  {
    "path": "src/main/java/lsieun/asm/core/ClassRemoveAttributeVisitor.java",
    "chars": 592,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\n\npublic class ClassRemoveAttributeVisitor extends Class"
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodAroundVisitor.java",
    "chars": 2163,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org.obje"
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodAroundVisitor2.java",
    "chars": 2165,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org.obje"
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodEmptyBodyVisitor.java",
    "chars": 3064,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org.obje"
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodEnterVisitor.java",
    "chars": 1379,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.Label;\nimport org.objectweb.as"
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodExitVisitor.java",
    "chars": 1442,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org.obje"
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodFindInvokeVisitor.java",
    "chars": 1855,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org.obje"
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodFindRefVisitor.java",
    "chars": 2920,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\nimport java.ut"
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodParameterVisitor.java",
    "chars": 7752,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org.obje"
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodParameterVisitor2.java",
    "chars": 4355,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org.obje"
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodPatternAdapter.java",
    "chars": 3502,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.Handle;\nimport org.objectweb.asm.Label;\nimport org.objectweb.asm.Meth"
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodRemoveAddZeroVisitor.java",
    "chars": 2200,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\nimport static "
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodRemoveGetFieldPutFieldVisitor.java",
    "chars": 3993,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\nimport static "
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodRemoveNopVisitor.java",
    "chars": 1300,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\nimport static "
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodRemovePrintVisitor.java",
    "chars": 3894,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\nimport static "
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodReplaceInvokeVisitor.java",
    "chars": 2500,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\nimport static "
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodTimerVisitor.java",
    "chars": 2850,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.FieldVisitor;\nimport org.objec"
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodTimerVisitor2.java",
    "chars": 3136,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.FieldVisitor;\nimport org.objec"
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodTimerVisitor3.java",
    "chars": 3265,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org.obje"
  },
  {
    "path": "src/main/java/lsieun/asm/core/MethodTimerVisitor4.java",
    "chars": 2879,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org.obje"
  },
  {
    "path": "src/main/java/lsieun/asm/core/SuperPackageAttribute.java",
    "chars": 926,
    "preview": "package lsieun.asm.core;\n\nimport org.objectweb.asm.*;\n\npublic class SuperPackageAttribute extends Attribute {\n    public"
  },
  {
    "path": "src/main/java/lsieun/asm/core/counter/ClassCounterVisitor.java",
    "chars": 1327,
    "preview": "package lsieun.asm.core.counter;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.FieldVisitor;\nimport o"
  },
  {
    "path": "src/main/java/lsieun/asm/core/counter/MethodCounterAdapter.java",
    "chars": 707,
    "preview": "package lsieun.asm.core.counter;\n\nimport org.objectweb.asm.MethodVisitor;\n\nimport static org.objectweb.asm.Opcodes.*;\n\np"
  },
  {
    "path": "src/main/java/lsieun/asm/core/empty/EmptyAnnotationVisitor.java",
    "chars": 270,
    "preview": "package lsieun.asm.core.empty;\n\nimport org.objectweb.asm.AnnotationVisitor;\n\npublic class EmptyAnnotationVisitor extends"
  },
  {
    "path": "src/main/java/lsieun/asm/core/empty/EmptyClassVisitor.java",
    "chars": 1799,
    "preview": "package lsieun.asm.core.empty;\n\nimport org.objectweb.asm.*;\n\npublic class EmptyClassVisitor extends ClassVisitor {\n    p"
  },
  {
    "path": "src/main/java/lsieun/asm/core/empty/EmptyFieldVisitor.java",
    "chars": 235,
    "preview": "package lsieun.asm.core.empty;\n\nimport org.objectweb.asm.FieldVisitor;\n\npublic class EmptyFieldVisitor extends FieldVisi"
  },
  {
    "path": "src/main/java/lsieun/asm/core/empty/EmptyMethodVisitor.java",
    "chars": 242,
    "preview": "package lsieun.asm.core.empty;\n\nimport org.objectweb.asm.MethodVisitor;\n\npublic class EmptyMethodVisitor extends MethodV"
  },
  {
    "path": "src/main/java/lsieun/asm/core/empty/EmptyModuleVisitor.java",
    "chars": 242,
    "preview": "package lsieun.asm.core.empty;\n\nimport org.objectweb.asm.ModuleVisitor;\n\npublic class EmptyModuleVisitor extends ModuleV"
  },
  {
    "path": "src/main/java/lsieun/asm/core/empty/EmptyRecordComponentVisitor.java",
    "chars": 305,
    "preview": "package lsieun.asm.core.empty;\n\nimport org.objectweb.asm.RecordComponentVisitor;\n\npublic class EmptyRecordComponentVisit"
  },
  {
    "path": "src/main/java/lsieun/asm/core/info/InfoClassVisitor.java",
    "chars": 3081,
    "preview": "package lsieun.asm.core.info;\n\nimport org.objectweb.asm.*;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport "
  },
  {
    "path": "src/main/java/lsieun/asm/core/info/InfoFieldVisitor.java",
    "chars": 411,
    "preview": "package lsieun.asm.core.info;\n\nimport org.objectweb.asm.FieldVisitor;\n\npublic class InfoFieldVisitor extends FieldVisito"
  },
  {
    "path": "src/main/java/lsieun/asm/core/info/InfoMethodVisitor.java",
    "chars": 3653,
    "preview": "package lsieun.asm.core.info;\n\nimport org.objectweb.asm.Label;\nimport org.objectweb.asm.MethodVisitor;\nimport org.object"
  },
  {
    "path": "src/main/java/lsieun/asm/core/timer/ClassTimerVisitor.java",
    "chars": 1371,
    "preview": "package lsieun.asm.core.timer;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.FieldVisitor;\nimport org"
  },
  {
    "path": "src/main/java/lsieun/asm/core/timer/MethodTimerAdapter.java",
    "chars": 1122,
    "preview": "package lsieun.asm.core.timer;\n\nimport org.objectweb.asm.MethodVisitor;\n\nimport static org.objectweb.asm.Opcodes.*;\n\npub"
  },
  {
    "path": "src/main/java/lsieun/asm/template/CheckMethodAnnotationVisitor.java",
    "chars": 1588,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.AnnotationVisitor;\nimport org.objectweb.asm.ClassVisitor;\nimport "
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassAddAnnotationVisitor.java",
    "chars": 2109,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.*;\n\npublic class ClassAddAnnotationVisitor extends ClassVisitor {"
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassAddCustomAttributeVisitor.java",
    "chars": 2233,
    "preview": "package lsieun.asm.template;\n\nimport lsieun.utils.ByteUtils;\nimport org.objectweb.asm.*;\n\npublic class ClassAddCustomAtt"
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassAddFieldVisitor.java",
    "chars": 1168,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.FieldVisitor;\n\npublic clas"
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassAddInterfaceVisitor.java",
    "chars": 910,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\n\nimport java.util.Arrays;\nimport java.util.HashSet;"
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassAddMethodVisitor.java",
    "chars": 1650,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\npublic abs"
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassGetAttributeContentVisitor.java",
    "chars": 1218,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.FieldVisitor;\nimport org.o"
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassMergeVisitor.java",
    "chars": 962,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.tree.ClassNode;\nimport org"
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassMergeVisitorRun.java",
    "chars": 2516,
    "preview": "package lsieun.asm.template;\n\nimport lsieun.utils.FileUtils;\nimport lsieun.utils.ReadUtils;\nimport org.objectweb.asm.Cla"
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassPrintAnnotationVisitor.java",
    "chars": 3789,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.AnnotationVisitor;\nimport org.objectweb.asm.ClassVisitor;\nimport "
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassPrintParameterVisitor.java",
    "chars": 2829,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org."
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassRemoveFieldVisitor.java",
    "chars": 790,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.FieldVisitor;\n\npublic clas"
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassRemoveMethodVisitor.java",
    "chars": 818,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\npublic cla"
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassRenameAdapter.java",
    "chars": 2099,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.FieldVisitor;\nimport org.o"
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassRenameAdapterRun.java",
    "chars": 1272,
    "preview": "package lsieun.asm.template;\n\nimport lsieun.utils.FileUtils;\nimport lsieun.utils.ReadUtils;\nimport org.objectweb.asm.Cla"
  },
  {
    "path": "src/main/java/lsieun/asm/template/ClassReplaceMethodBodyVisitor.java",
    "chars": 2291,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\npublic abs"
  },
  {
    "path": "src/main/java/lsieun/asm/template/CustomAttribute.java",
    "chars": 1617,
    "preview": "package lsieun.asm.template;\n\nimport lsieun.utils.ByteUtils;\nimport lsieun.utils.HexFormat;\nimport lsieun.utils.HexUtils"
  },
  {
    "path": "src/main/java/lsieun/asm/template/FieldAccessAdapter.java",
    "chars": 709,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\nimport jav"
  },
  {
    "path": "src/main/java/lsieun/asm/template/FieldAccessAdapterRun.java",
    "chars": 1451,
    "preview": "package lsieun.asm.template;\n\nimport lsieun.utils.FileUtils;\nimport lsieun.utils.ReadUtils;\nimport org.objectweb.asm.Cla"
  },
  {
    "path": "src/main/java/lsieun/asm/template/FieldAccessConverter.java",
    "chars": 1279,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.MethodVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List"
  },
  {
    "path": "src/main/java/lsieun/asm/template/Info.java",
    "chars": 811,
    "preview": "package lsieun.asm.template;\n\npublic class Info {\n    public final int srcOpcode;\n    public final String srcOwner;\n    "
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodCallAdapter.java",
    "chars": 706,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\nimport jav"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodCallAdapterRun.java",
    "chars": 1260,
    "preview": "package lsieun.asm.template;\n\nimport lsieun.utils.FileUtils;\nimport lsieun.utils.ReadUtils;\nimport org.objectweb.asm.Cla"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodCallConverter.java",
    "chars": 1313,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.MethodVisitor;\n\nimport java.util.ArrayList;\nimport java.util.List"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodEnteringAdapter.java",
    "chars": 741,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.commons.AdviceAdapter;\n\np"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodEnteringVisitor.java",
    "chars": 633,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\npublic cla"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodEnteringVisitorRun.java",
    "chars": 951,
    "preview": "package lsieun.asm.template;\n\nimport lsieun.utils.FileUtils;\nimport lsieun.utils.ReadUtils;\nimport org.objectweb.asm.Cla"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodExitingAdapter.java",
    "chars": 632,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\npublic cla"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodExitingAdapterRun.java",
    "chars": 971,
    "preview": "package lsieun.asm.template;\n\nimport lsieun.utils.FileUtils;\nimport lsieun.utils.ReadUtils;\nimport org.objectweb.asm.Cla"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodExitingConverter.java",
    "chars": 950,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.Opcodes;\nimport org.objec"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodFinallyAdapter.java",
    "chars": 655,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\npublic cla"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodFinallyAdapterRun.java",
    "chars": 971,
    "preview": "package lsieun.asm.template;\n\nimport lsieun.utils.FileUtils;\nimport lsieun.utils.ReadUtils;\nimport org.objectweb.asm.Cla"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodFinallyConverter.java",
    "chars": 1454,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.Label;\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectw"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodPrintInstructionAdapter.java",
    "chars": 9001,
    "preview": "package lsieun.asm.template;\n\nimport lsieun.utils.OpcodeConst;\nimport org.objectweb.asm.Handle;\nimport org.objectweb.asm"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodPrintInstructionVisitor.java",
    "chars": 1038,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\n\nimport sta"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodWithSameTryCatchLogicVisitor.java",
    "chars": 2230,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.Label;\nimport org.objectwe"
  },
  {
    "path": "src/main/java/lsieun/asm/template/MethodWithWholeTryCatchVisitor.java",
    "chars": 3317,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.*;\n\nimport static org.objectweb.asm.Opcodes.*;\n\npublic class Meth"
  },
  {
    "path": "src/main/java/lsieun/asm/template/RefRenameAdapter.java",
    "chars": 1592,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.Type;\n\npublic class RefRe"
  },
  {
    "path": "src/main/java/lsieun/asm/template/RemoveSyntheticVisitor.java",
    "chars": 1113,
    "preview": "package lsieun.asm.template;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.FieldVisitor;\nimport org.o"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/ChangeMemberNameBasedOnAnnotationNode.java",
    "chars": 1382,
    "preview": "package lsieun.asm.tree;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.tree.AnnotationNode;\nimport or"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/ChangeThisNode.java",
    "chars": 5912,
    "preview": "package lsieun.asm.tree;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org.obje"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/ClassAddCustomAttributeNode.java",
    "chars": 1359,
    "preview": "package lsieun.asm.tree;\n\nimport lsieun.asm.template.CustomAttribute;\nimport lsieun.utils.ByteUtils;\nimport org.objectwe"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/ClassAddFieldNode.java",
    "chars": 2034,
    "preview": "package lsieun.asm.tree;\n\nimport lsieun.asm.tree.transformer.ClassTransformer;\nimport org.objectweb.asm.ClassVisitor;\nim"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/ClassAddMethodNode.java",
    "chars": 2659,
    "preview": "package lsieun.asm.tree;\n\nimport lsieun.asm.tree.transformer.ClassTransformer;\nimport org.objectweb.asm.ClassVisitor;\nim"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/ClassAddTimerNode.java",
    "chars": 2760,
    "preview": "package lsieun.asm.tree;\n\nimport lsieun.asm.tree.transformer.ClassTransformer;\nimport org.objectweb.asm.ClassVisitor;\nim"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/ClassRemoveFieldNode.java",
    "chars": 1501,
    "preview": "package lsieun.asm.tree;\n\nimport lsieun.asm.tree.transformer.ClassTransformer;\nimport org.objectweb.asm.ClassVisitor;\nim"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/ClassRemoveMethodNode.java",
    "chars": 1527,
    "preview": "package lsieun.asm.tree;\n\nimport lsieun.asm.tree.transformer.ClassTransformer;\nimport org.objectweb.asm.ClassVisitor;\nim"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/MixCore2TreeVisitor.java",
    "chars": 2015,
    "preview": "package lsieun.asm.tree;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org.obje"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/MixTree2CoreNode.java",
    "chars": 1440,
    "preview": "package lsieun.asm.tree;\n\nimport lsieun.asm.template.MethodEnteringAdapter;\nimport org.objectweb.asm.ClassVisitor;\nimpor"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/OptimizeJumpNode.java",
    "chars": 2747,
    "preview": "package lsieun.asm.tree;\n\nimport lsieun.asm.tree.transformer.MethodTransformer;\nimport org.objectweb.asm.ClassVisitor;\ni"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/RemoveGetFieldPutFieldNode.java",
    "chars": 3698,
    "preview": "package lsieun.asm.tree;\n\nimport lsieun.asm.tree.transformer.MethodTransformer;\nimport org.objectweb.asm.ClassVisitor;\ni"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/my/MyClassNode.java",
    "chars": 536,
    "preview": "package lsieun.asm.tree.my;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.tree.ClassNode;\n\npublic cla"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/my/MyClassVisitor.java",
    "chars": 668,
    "preview": "package lsieun.asm.tree.my;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.tree.ClassNode;\n\npublic cla"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/my/MyMethodAdapter.java",
    "chars": 804,
    "preview": "package lsieun.asm.tree.my;\n\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.tree.MethodNode;\n\npublic c"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/my/MyMethodNode.java",
    "chars": 709,
    "preview": "package lsieun.asm.tree.my;\n\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.tree.MethodNode;\n\npublic c"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/transformer/ClassTransformer.java",
    "chars": 353,
    "preview": "package lsieun.asm.tree.transformer;\n\nimport org.objectweb.asm.tree.ClassNode;\n\npublic abstract class ClassTransformer {"
  },
  {
    "path": "src/main/java/lsieun/asm/tree/transformer/MethodTransformer.java",
    "chars": 359,
    "preview": "package lsieun.asm.tree.transformer;\n\nimport org.objectweb.asm.tree.MethodNode;\n\npublic abstract class MethodTransformer"
  },
  {
    "path": "src/main/java/lsieun/asm/util/CheckClassAdapterExample01Generate.java",
    "chars": 901,
    "preview": "package lsieun.asm.util;\n\nimport lsieun.utils.FileUtils;\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm"
  },
  {
    "path": "src/main/java/lsieun/asm/util/CheckClassAdapterExample02Generate.java",
    "chars": 1036,
    "preview": "package lsieun.asm.util;\n\nimport lsieun.utils.FileUtils;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm."
  },
  {
    "path": "src/main/java/lsieun/asm/util/CodeUtils.java",
    "chars": 1432,
    "preview": "package lsieun.asm.util;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.FieldVisitor;\nimport org.objec"
  },
  {
    "path": "src/main/java/lsieun/asm/util/TraceClassVisitorExample01Generate.java",
    "chars": 2332,
    "preview": "package lsieun.asm.util;\n\nimport lsieun.utils.FileUtils;\nimport org.objectweb.asm.ClassWriter;\nimport org.objectweb.asm."
  },
  {
    "path": "src/main/java/lsieun/asm/util/TraceClassVisitorExample02Transform.java",
    "chars": 1313,
    "preview": "package lsieun.asm.util;\n\nimport lsieun.asm.core.MethodTimerVisitor;\nimport lsieun.utils.FileUtils;\nimport org.objectweb"
  },
  {
    "path": "src/main/java/lsieun/asm/util/TraceClassVisitorExample03.java",
    "chars": 1084,
    "preview": "package lsieun.asm.util;\n\nimport static org.objectweb.asm.Opcodes.*;\n\nimport java.io.PrintWriter;\n\nimport org.objectweb."
  },
  {
    "path": "src/main/java/lsieun/asm/util/TreePrinter.java",
    "chars": 28925,
    "preview": "package lsieun.asm.util;\n\nimport org.objectweb.asm.*;\nimport org.objectweb.asm.util.Printer;\n\nimport java.util.Collectio"
  },
  {
    "path": "src/main/java/lsieun/classfile/CPInfo.java",
    "chars": 887,
    "preview": "package lsieun.classfile;\n\npublic class CPInfo {\n    static final int CONSTANT_UTF8_TAG = 1;\n\n    static final int CONST"
  },
  {
    "path": "src/main/java/lsieun/classfile/ClassFile.java",
    "chars": 8263,
    "preview": "package lsieun.classfile;\n\nimport java.util.Arrays;\n\npublic class ClassFile {\n    private final byte[] classFileBuffer;\n"
  },
  {
    "path": "src/main/java/lsieun/classfile/InsnRaw.java",
    "chars": 55741,
    "preview": "package lsieun.classfile;\n\nimport java.util.ArrayList;\nimport java.util.Formatter;\nimport java.util.List;\n\npublic class "
  },
  {
    "path": "src/main/java/lsieun/cst/Const.java",
    "chars": 498,
    "preview": "package lsieun.cst;\n\npublic class Const {\n    public static final boolean DEBUG = true;\n\n    public static final String "
  },
  {
    "path": "src/main/java/lsieun/drawing/canvas/Box.java",
    "chars": 1823,
    "preview": "package lsieun.drawing.canvas;\n\n/**\n * <ul>\n *     <li> LEFT: 0b1000</li>\n *     <li>   UP: 0b0100</li>\n *     <li>RIGHT"
  },
  {
    "path": "src/main/java/lsieun/drawing/canvas/Canvas.java",
    "chars": 10111,
    "preview": "package lsieun.drawing.canvas;\n\nimport lsieun.utils.StringUtils;\n\nimport java.util.ArrayList;\nimport java.util.Collectio"
  },
  {
    "path": "src/main/java/lsieun/drawing/canvas/Drawable.java",
    "chars": 120,
    "preview": "package lsieun.drawing.canvas;\n\npublic interface Drawable {\n    void draw(Canvas canvas, int startRow, int startCol);\n}\n"
  },
  {
    "path": "src/main/java/lsieun/drawing/canvas/TextAlign.java",
    "chars": 90,
    "preview": "package lsieun.drawing.canvas;\n\npublic enum TextAlign {\n    LEFT,\n    CENTER,\n    RIGHT\n}\n"
  },
  {
    "path": "src/main/java/lsieun/drawing/canvas/TextDirection.java",
    "chars": 100,
    "preview": "package lsieun.drawing.canvas;\n\npublic enum TextDirection {\n    UP,\n    DOWN,\n    LEFT,\n    RIGHT\n}\n"
  },
  {
    "path": "src/main/java/lsieun/drawing/canvas/TextPixel.java",
    "chars": 910,
    "preview": "package lsieun.drawing.canvas;\n\npublic class TextPixel implements Comparable<TextPixel> {\n    public int row;\n    public"
  },
  {
    "path": "src/main/java/lsieun/drawing/theme/line/ContinuousLine.java",
    "chars": 3085,
    "preview": "package lsieun.drawing.theme.line;\n\nimport lsieun.drawing.canvas.Box;\nimport lsieun.drawing.canvas.Canvas;\nimport lsieun"
  },
  {
    "path": "src/main/java/lsieun/drawing/theme/shape/Rectangle.java",
    "chars": 1344,
    "preview": "package lsieun.drawing.theme.shape;\n\nimport lsieun.drawing.canvas.Box;\nimport lsieun.drawing.canvas.Canvas;\nimport lsieu"
  },
  {
    "path": "src/main/java/lsieun/drawing/theme/shape/RectangleWithText.java",
    "chars": 1952,
    "preview": "package lsieun.drawing.theme.shape;\n\nimport lsieun.drawing.canvas.Canvas;\nimport lsieun.drawing.canvas.Drawable;\nimport "
  },
  {
    "path": "src/main/java/lsieun/drawing/theme/table/AbstractTable.java",
    "chars": 881,
    "preview": "package lsieun.drawing.theme.table;\n\nimport lsieun.drawing.canvas.Drawable;\n\npublic abstract class AbstractTable impleme"
  },
  {
    "path": "src/main/java/lsieun/drawing/theme/table/FixedWidthOneLineTable.java",
    "chars": 494,
    "preview": "package lsieun.drawing.theme.table;\n\nimport lsieun.drawing.canvas.Drawable;\nimport lsieun.drawing.canvas.TextAlign;\n\npub"
  },
  {
    "path": "src/main/java/lsieun/drawing/theme/table/OneLineTable.java",
    "chars": 2928,
    "preview": "package lsieun.drawing.theme.table;\n\nimport lsieun.drawing.canvas.Canvas;\nimport lsieun.drawing.canvas.Drawable;\nimport "
  },
  {
    "path": "src/main/java/lsieun/drawing/theme/text/PlainText.java",
    "chars": 921,
    "preview": "package lsieun.drawing.theme.text;\n\nimport lsieun.drawing.canvas.Canvas;\nimport lsieun.drawing.canvas.Drawable;\n\nimport "
  },
  {
    "path": "src/main/java/lsieun/trove/HashFunctions.java",
    "chars": 3124,
    "preview": "package lsieun.trove;\n\npublic final class HashFunctions {\n    /**\n     * Returns a hashcode for the specified value.\n   "
  },
  {
    "path": "src/main/java/lsieun/trove/PrimeFinder.java",
    "chars": 3958,
    "preview": "package lsieun.trove;\n\nimport java.util.Arrays;\n\npublic final class PrimeFinder {\n\t/**\n\t * The largest prime this class "
  },
  {
    "path": "src/main/java/lsieun/trove/THash.java",
    "chars": 8265,
    "preview": "package lsieun.trove;\n\npublic abstract class THash implements Cloneable {\n    /** the current number of occupied slots i"
  },
  {
    "path": "src/main/java/lsieun/trove/TIntArrayList.java",
    "chars": 24691,
    "preview": "package lsieun.trove;\n\nimport java.io.Serializable;\nimport java.util.Arrays;\nimport java.util.Objects;\nimport java.util."
  },
  {
    "path": "src/main/java/lsieun/trove/TIntFunction.java",
    "chars": 408,
    "preview": "package lsieun.trove;\n\n/**\n * Interface for functions that accept and return one int primitive.\n *\n * Created: Mon Nov  "
  },
  {
    "path": "src/main/java/lsieun/trove/TIntHash.java",
    "chars": 7828,
    "preview": "package lsieun.trove;\n\npublic abstract class TIntHash extends TPrimitiveHash\n    implements TIntHashingStrategy {\n\n    /"
  },
  {
    "path": "src/main/java/lsieun/trove/TIntHashingStrategy.java",
    "chars": 748,
    "preview": "package lsieun.trove;\n\nimport java.io.Serializable;\n\n/**\n * Interface to support pluggable hashing strategies in maps an"
  },
  {
    "path": "src/main/java/lsieun/trove/TIntIntHashMap.java",
    "chars": 13889,
    "preview": "package lsieun.trove;\n\npublic class TIntIntHashMap extends TIntHash {\n\n    /**\n     * the values of the map\n     */\n    "
  },
  {
    "path": "src/main/java/lsieun/trove/TIntIntIterator.java",
    "chars": 1765,
    "preview": "package lsieun.trove;\n\npublic class TIntIntIterator extends TPrimitiveIterator {\n    /**\n     * the collection being ite"
  },
  {
    "path": "src/main/java/lsieun/trove/TIntIntProcedure.java",
    "chars": 468,
    "preview": "package lsieun.trove;\n\npublic interface TIntIntProcedure {\n\n    /**\n     * Executes this procedure. A false return value"
  },
  {
    "path": "src/main/java/lsieun/trove/TIntProcedure.java",
    "chars": 427,
    "preview": "package lsieun.trove;\n\npublic interface TIntProcedure {\n    /**\n     * Executes this procedure. A false return value ind"
  },
  {
    "path": "src/main/java/lsieun/trove/TIterator.java",
    "chars": 2354,
    "preview": "package lsieun.trove;\n\nimport java.util.ConcurrentModificationException;\nimport java.util.NoSuchElementException;\n\n/**\n "
  },
  {
    "path": "src/main/java/lsieun/trove/TPrimitiveHash.java",
    "chars": 2841,
    "preview": "package lsieun.trove;\n\npublic abstract class TPrimitiveHash extends THash {\n    /** flags indicating whether each positi"
  },
  {
    "path": "src/main/java/lsieun/trove/TPrimitiveIterator.java",
    "chars": 1740,
    "preview": "package lsieun.trove;\n\nimport java.util.ConcurrentModificationException;\n\n/**\n * Implements all iterator functions for t"
  },
  {
    "path": "src/main/java/lsieun/trove/package-info.java",
    "chars": 317,
    "preview": "/**\n * 这个包下的代码是从trove4j复制过来的.\n * <p>\n * 当前项目的主要关注点就是Java ASM,因此在pom.xml文件中我想只引用ASM相关的jar包,尽量避免引用别的jar包。\n * </p>\n * <p>\n "
  },
  {
    "path": "src/main/java/lsieun/utils/ASMUtilsCore.java",
    "chars": 2535,
    "preview": "package lsieun.utils;\n\nimport org.objectweb.asm.*;\n\npublic class ASMUtilsCore {\n    public int read(ClassReader cr, int "
  },
  {
    "path": "src/main/java/lsieun/utils/ASMUtilsTree.java",
    "chars": 2178,
    "preview": "package lsieun.utils;\n\nimport org.objectweb.asm.tree.*;\nimport org.objectweb.asm.tree.analysis.*;\n\npublic class ASMUtils"
  },
  {
    "path": "src/main/java/lsieun/utils/BoxDrawingUtils.java",
    "chars": 3733,
    "preview": "package lsieun.utils;\n\nimport lsieun.asm.analysis.InsnText;\nimport lsieun.drawing.canvas.Box;\nimport lsieun.drawing.canv"
  },
  {
    "path": "src/main/java/lsieun/utils/ByteArrayClassLoader.java",
    "chars": 563,
    "preview": "package lsieun.utils;\n\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.Type;\n\npublic class ByteArrayClass"
  },
  {
    "path": "src/main/java/lsieun/utils/ByteUtils.java",
    "chars": 1688,
    "preview": "package lsieun.utils;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.nio.ByteBuffer;\n\npu"
  },
  {
    "path": "src/main/java/lsieun/utils/DescriptorUtils.java",
    "chars": 612,
    "preview": "package lsieun.utils;\n\npublic class DescriptorUtils {\n    public static String simplify(String descriptor) {\n        int"
  },
  {
    "path": "src/main/java/lsieun/utils/FileUtils.java",
    "chars": 6254,
    "preview": "package lsieun.utils;\n\nimport lsieun.cst.Const;\n\nimport java.io.*;\nimport java.nio.charset.StandardCharsets;\nimport java"
  },
  {
    "path": "src/main/java/lsieun/utils/FrameUtils.java",
    "chars": 7845,
    "preview": "package lsieun.utils;\n\nimport lsieun.asm.analysis.InsnText;\nimport lsieun.cst.Const;\nimport lsieun.drawing.canvas.Canvas"
  },
  {
    "path": "src/main/java/lsieun/utils/HexFormat.java",
    "chars": 631,
    "preview": "package lsieun.utils;\n\npublic enum HexFormat {\n    FORMAT_FF_FF(\"\", 0),\n    FORMAT_FF_FF_8(\"\", 8),\n    FORMAT_FF_FF_16(\""
  },
  {
    "path": "src/main/java/lsieun/utils/HexUtils.java",
    "chars": 2290,
    "preview": "package lsieun.utils;\n\nimport java.util.Formatter;\n\npublic class HexUtils {\n\n    public static String format(byte[] byte"
  }
]

// ... and 31 more files (download for full content)

About this extraction

This page contains the full source code of the lsieun/learn-java-asm GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 231 files (615.8 KB), approximately 150.2k tokens, and a symbol index with 1337 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!