内容回顾
首先,我们要强调:在asm-analysis.jar
当中,最重要的类就是Analyzer
、Frame
、Interpreter
和Value
四个类。
其次,贯穿本章内容的核心就是下面两行代码:
┌── Analyzer
│ ┌── Value ┌── Interpreter
│ │ │
Analyzer<BasicValue> analyzer = new Analyzer<>(new BasicInterpreter());
Frame<BasicValue>[] frames = analyzer.analyze(owner, mn);
│ │
│ └── Value
└── Frame
在这两行代码当中,用到了Analyzer
、Frame
、Interpreter
和Value
这四个类:
- 第一行代码,使用
Interpreter
来创建Analyzer
对象。 - 第二行代码,调用
Analyzer.analyze
方法生成Frame<?>[]
信息,之后可以进行各种不同类型的分析。
再者,这四个类当中,Analyzer
和Frame
是相对固定的,而Interpreter
和Value
是变化的:
┌──────────┬─────────────┐
│ │ Analyzer │
│ Fixed ├─────────────┤
│ │ Frame │
├──────────┼─────────────┤
│ │ Interpreter │
│ Variable ├─────────────┤
│ │ Value │
└──────────┴─────────────┘
最后,Interpreter
和Value
类有不同的具体表现形式:
┌───┬───────────────────┬─────────────┬───────┐
│ 0 │ Interpreter │ Value │ Range │
├───┼───────────────────┼─────────────┼───────┤
│ 1 │ BasicInterpreter │ BasicValue │ 7 │
├───┼───────────────────┼─────────────┼───────┤
│ 2 │ BasicVerifier │ BasicValue │ 7 │
├───┼───────────────────┼─────────────┼───────┤
│ 3 │ SimpleVerifier │ BasicValue │ N │
├───┼───────────────────┼─────────────┼───────┤
│ 4 │ SourceInterpreter │ SourceValue │ N │
└───┴───────────────────┴─────────────┴───────┘
回顾了这些内容之后,我们再来看一下Interpreter
和Value
的精妙之处。
Interpreter类的精妙之处
Interpreter
类的精妙之处体现在它的功能上,我们从三点来把握,来欣赏Interpreter
类的“艺术和美”。
第一点,从功能的角度来讲,Interpreter
类与Frame
类的功能分割恰到好处:入栈和出栈的操作交给了Frame
来进行处理,而具体的入栈和出栈的值是由Interpreter
来处理的。举一个生活中的例子,国有资本(Government Capital,相当于Frame
类)新建了一个高铁站,进入车站的车辆和离开车站的车辆是它来负责的;具体的运作交给民营资本(Private Investment,相当于Interpreter
类),每辆车上装载的是货物还是人是由它来决定的。
第二点,从opcode的角度来讲,它将原本200多个opcode分类成(浓缩成)了7个方法,分类的依据就是使用的(或者说,消耗的、出栈的、入栈的)元素数量来决定的。
public abstract class Interpreter {
public abstract Value newOperation(AbstractInsnNode insn) throws AnalyzerException;
public abstract Value copyOperation(AbstractInsnNode insn, Value value) throws AnalyzerException;
public abstract Value unaryOperation(AbstractInsnNode insn, Value value) throws AnalyzerException;
public abstract Value binaryOperation(AbstractInsnNode insn, Value value1, Value value2) throws AnalyzerException;
public abstract Value ternaryOperation(AbstractInsnNode insn, Value value1, Value value2, Value value3) throws AnalyzerException;
public abstract Value naryOperation(AbstractInsnNode insn, List<Value> values) throws AnalyzerException;
public abstract void returnOperation(AbstractInsnNode insn, Value value, Value expected) throws AnalyzerException;
}
第三点,从Value
的角度来讲,Interpreter
类决定了Value
类对象的数量、表达能力。一般来说,Value
类对象的数量越多,它的表达能力越丰富。举个生活当中的例子,这有点类似于“计划生育”,Interpreter
类决定了Value
类的数量。
Value类的表达能力
在Frame当中,我们可以存储的Value
值有两种:类型(type或者class)和实例对象(object或者instance)。
public class HelloWorld {
public void test() {
int a = 1;
int b = 2;
String str1 = "Hello";
String str2 = "World";
Object obj1 = new Object();
Object obj2 = new Object();
}
}
如果使用BasicInterpreter
类,那么BasicValue
值的表达能力(类型)如下:每个类型
test:()V
000: iconst_1 {R, ., ., ., ., ., .} | {}
001: istore_1 {R, ., ., ., ., ., .} | {I}
002: iconst_2 {R, I, ., ., ., ., .} | {}
003: istore_2 {R, I, ., ., ., ., .} | {I}
004: ldc "Hello" {R, I, I, ., ., ., .} | {}
005: astore_3 {R, I, I, ., ., ., .} | {R}
006: ldc "World" {R, I, I, R, ., ., .} | {}
007: astore 4 {R, I, I, R, ., ., .} | {R}
008: new Object {R, I, I, R, R, ., .} | {}
009: dup {R, I, I, R, R, ., .} | {R}
010: invokespecial Object.<init> {R, I, I, R, R, ., .} | {R, R}
011: astore 5 {R, I, I, R, R, ., .} | {R}
012: new Object {R, I, I, R, R, R, .} | {}
013: dup {R, I, I, R, R, R, .} | {R}
014: invokespecial Object.<init> {R, I, I, R, R, R, .} | {R, R}
015: astore 6 {R, I, I, R, R, R, .} | {R}
016: return {R, I, I, R, R, R, R} | {}
================================================================
如果使用SimpleVerifier
类,那么BasicValue
值的表达能力(对象实例)如下:每个不同的对象对应一个BasicValue
值。
test:()V
000: iconst_1 {HelloWorld, ., ., ., ., ., .} | {}
001: istore_1 {HelloWorld, ., ., ., ., ., .} | {I}
002: iconst_2 {HelloWorld, I, ., ., ., ., .} | {}
003: istore_2 {HelloWorld, I, ., ., ., ., .} | {I}
004: ldc "Hello" {HelloWorld, I, I, ., ., ., .} | {}
005: astore_3 {HelloWorld, I, I, ., ., ., .} | {String}
006: ldc "World" {HelloWorld, I, I, String, ., ., .} | {}
007: astore 4 {HelloWorld, I, I, String, ., ., .} | {String}
008: new Object {HelloWorld, I, I, String, String, ., .} | {}
009: dup {HelloWorld, I, I, String, String, ., .} | {Object}
010: invokespecial Object.<init> {HelloWorld, I, I, String, String, ., .} | {Object, Object}
011: astore 5 {HelloWorld, I, I, String, String, ., .} | {Object}
012: new Object {HelloWorld, I, I, String, String, Object, .} | {}
013: dup {HelloWorld, I, I, String, String, Object, .} | {Object}
014: invokespecial Object.<init> {HelloWorld, I, I, String, String, Object, .} | {Object, Object}
015: astore 6 {HelloWorld, I, I, String, String, Object, .} | {Object}
016: return {HelloWorld, I, I, String, String, Object, Object} | {}
================================================================
如果使用SourceInterpreter
类,那么SourceValue
值的表达能力(对象实例)如下:差不多每个instruction都会生成一个新的SourceValue
对象
test:()V
000: iconst_1 {[], [], [], [], [], [], []} | {}
001: istore_1 {[], [], [], [], [], [], []} | {[iconst_1]}
002: iconst_2 {[], [istore_1], [], [], [], [], []} | {}
003: istore_2 {[], [istore_1], [], [], [], [], []} | {[iconst_2]}
004: ldc "Hello" {[], [istore_1], [istore_2], [], [], [], []} | {}
005: astore_3 {[], [istore_1], [istore_2], [], [], [], []} | {[ldc "Hello"]}
006: ldc "World" {[], [istore_1], [istore_2], [astore_3], [], [], []} | {}
007: astore 4 {[], [istore_1], [istore_2], [astore_3], [], [], []} | {[ldc "World"]}
008: new Object {[], [istore_1], [istore_2], [astore_3], [astore 4], [], []} | {}
009: dup {[], [istore_1], [istore_2], [astore_3], [astore 4], [], []} | {[new Object]}
010: invokespecial Object.<init> {[], [istore_1], [istore_2], [astore_3], [astore 4], [], []} | {[new Object], [dup]}
011: astore 5 {[], [istore_1], [istore_2], [astore_3], [astore 4], [], []} | {[new Object]}
012: new Object {[], [istore_1], [istore_2], [astore_3], [astore 4], [astore 5], []} | {}
013: dup {[], [istore_1], [istore_2], [astore_3], [astore 4], [astore 5], []} | {[new Object]}
014: invokespecial Object.<init> {[], [istore_1], [istore_2], [astore_3], [astore 4], [astore 5], []} | {[new Object], [dup]}
015: astore 6 {[], [istore_1], [istore_2], [astore_3], [astore 4], [astore 5], []} | {[new Object]}
016: return {[], [istore_1], [istore_2], [astore_3], [astore 4], [astore 5], [astore 6]} | {}
================================================================
我们暂时不考虑primitive type(int
、float
、long
和double
类型),只考虑reference type:
模拟类型(抽象): R - BasicInterpreter, BasicVerifier
模拟类型(具体): Integer, String, Object - StackMapTable
模拟对象(具体): Integer(1), Integer(2), String("AAA"), String("BBB"), Object(obj1), Object(obj2) - SimpleVerifier
模拟指令(超级具体): 每个指令对应一个Value对象 - SourceInterpreter
那么Value
的表达能力可以描述成这样:
┌─── abstract type
│
├─── concrete type
Value ───┤
├─── concrete object
│
└─── instruction-based object
总结
本文内容总结如下:
- 第一点,把握
Interpreter
类的精妙之处就是结合Frame
(功能切割)、opcode(方法定义)和Value
(表达能力)来理解。 - 第二点,把握
Value
类的精妙之处在于理解四个不同层次的表达。