内容回顾
首先,我们要强调:在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类的精妙之处在于理解四个不同层次的表达。