ASMSupportチュートリアル4:共通アクションの生成
5318 ワード
前言4.1
チュートリアルが始まる前に、まず操作を生成するバイトコードコマンドの原理を簡単に紹介します.Javaコードの中で私たちの最も基本的な演算は操作であることを知っています.例えば、4つの演算、方法呼び出しなど、コードなどです.
ここには6種類の操作があります.
操作である以上操作因子がありますが、操作因子とは何ですか?次の表を参照してください.
コード#コード#
オペレーションファクタ
String a = "str";
"str"
int i = 1 + 2;
1, 2, 1+2
i++;
i
System.out.println(a + i)
a, i, a + 1
全部で10種類の操作が存在し、具体的には以下の通りである(ここでは各操作の1つのみを列挙し、すべて列挙しない).
1. String a = "str"; =:割り当て
2. i++;++:インクリメンタル操作
3. int i = 1 + 2; +:演算演算演算=:代入
4.9&7&:ビット操作
5.a>1>:関係演算操作
6.true&&false&&:論理演算操作7.k = i < 0 ? -i : i _さんげんそうさ
8.a instanceof String instanceof:instanceof操作9."Hello "+ "asmsupport!"+:文字列の結合操作10.System.out.println(a + i); _2番目".":メソッド呼び出しアクション
私たちのプログラムでは、すべての操作をIBlockOperatorsのメソッド呼び出しで実現します.すべての操作因子はメソッドパラメータによって伝達される.また,ある操作は同様に他の操作の操作因子とすることができ,上記の1+2が付与操作"="としての操作因子である.asmsupportではjwを継承する限り.asmsupport.Parameterizedインタフェースは、いずれも操作因子として使用できます.実はasmsupportを使用する場合、javaコードで操作因子として使用できるのはasmsupportでも操作因子として使用できるのがほとんどです.asmsupportはjavaコードの作成方法を保持しているからです.ここではASMSupportを使ったアングルでご紹介します.
ここでは、これらの操作が最下位でどのように実現されているかを簡単に説明します.ASMSupportではjava操作をクラスAbstractOperatorとして抽象化する.class、各具体的な操作はそれから継承されています.例えばinstanceof操作はjwに抽象化します.asmsupport.operators.InstanceofOperator.AbstraactOperatorはjwも継承する.asmsupport.Executeableインタフェースです.このインタフェースには2つの方法があります. prepare() execute()
各操作はExecuteableインタフェースに相当します.ASMSupportは、各対応するExecuteableを1つのListで所望のコードの順序でこのListに格納します(実行キューにはプログラムブロックjw.asmsupport.block.ProgramBlockも格納します).すべての操作を実行キューに格納した後、すべての操作を巡回し、すべての操作に対してprepareメソッドを実行し、再び実行キューを巡回します.各要素に対してexecuteメソッドを実行します.prepareメソッドの役割は実行キューを統合し再配置することであり,executeメソッドはバイトコード命令を生成することである.たとえば、次のコードを生成します.
ASMSupportで生成されたこのコードは次のとおりです.
私たちはそれぞれ100,10,1をValueを通過することを見ることができます.value()メソッドは、対応するjwを生成する.asmsupport.definition.value.Valueオブジェクト.addメソッドはjwを返す.asmsupport.operators.numerical.arithmetic.Additionオブジェクト、createVariableメソッドはjwを返します.asmsupport.definition.variable.LocalVariableオブジェクト、invokeメソッドはjwを返します.asmsupport.operators.method.MethodInvoker.私はリスト形式ですべてのオブジェクトが作成された順序をリストします.順序は一番上の最初の作成です.
シーケンス番号
ASMSupportコード
結果タイプを返す
対応javaコード
1
Value.value(100)
jw.asmsupport.definition.value.Value
数値100
2
Value.value(10)
jw.asmsupport.definition.value.Value
数値10
3
this.add()
jw.asmsupport.operators.numerical.arithmetic.Addition
加算操作(100+10)
4
createVariable()
jw.asmsupport.definition.variable.LocalVariable
変数を作成し、上記の加算操作の結果をこの変数valueに格納します.ここではLocalVariableを返すが、このコードを実行するときも内部にjwが作成される.asmsupport.operators.variable.LocalVariableCreatorオブジェクトとjw.asmsupport.operators.assign.Assignerオブジェクトは、JVMレベルでメソッドのローカル変数に変数を登録する役割を果たす変数を作成します.
5
...getGlobalVariable("out")
jw.asmsupport.definition.variable.GlobalVariable
システムを取得します.out
6
Value.value(1)
jw.asmsupport.definition.value.Value
数値1
7
add(value, Value.value(1))
jw.asmsupport.operators.numerical.arithmetic.Addition
加算アクション:value+1
8
invoke(...)
jw.asmsupport.operators.method.MethodInvoker
メソッド呼び出し操作は、1番目のパラメータがメソッドの所有者である、メソッド名が2番目のパラメータであり、残りのパラメータが呼び出すメソッドのパラメータを表し、ここでSystemを表す.out.println(value + 1)
上記の手順に従って実行が完了すると、ASMSupportは、上記で作成したExecuteableタイプのオブジェクト(可視ソースコード:jw.asmsupport.block.ProgramBlockのexecuteQueue)を実行キュー(Listタイプ)で保存し、ソースコードによって、すべてのブロックProgramBlockおよびそのサブクラス、すべての操作(AbstraactOperatorのサブクラス)、グローバル変数操作GlobalVariableCreatorとメソッドを作成するMethodCreatorはExecuteableのメソッドを実現しています.次のような実行キューが得られます.
オブジェクト
別名#ベツメイ#
対応コード
Addition
add1
100 + 10
LocalVariableCreator
Assigner
ass1
Addition
add2
MethodInvoker
mi
System.out.println(...)
他のオブジェクトについては、コードを通じて、Valueのような対応する操作クラスに転送されていることがわかります.value(100)とValue.value(10)はadd 1に伝わった.すべてのオブジェクトがセットされた後、prepareメソッドが1つずつ実行されると、実行後の実行キューは次のようになります.
オブジェクト
別名#ベツメイ#
対応コード
Assigner
ass1
value = add1
MethodInvoker
mi
System.out.println(...);
なぜprepareが実行された後に実行キューがadd 1,add 2を除去するのかというと、prepareがこのキューを巡ったときに各キュー内のオブジェクトに対して判断されると他のオブジェクトに参照され、他の参照されると削除され、executeメソッドを実行する制御権が参照されるオブジェクトに渡されるからである.プログラムはどのように他の操作に引用されたかを判断するか,ParameterizedインタフェースのasArgument()メソッドを通過する.コードでthisが見えます.add(Value.value(100), Value.value(10))このコードの戻り値はcreateVariableメソッドによって参照される.add(value,Value.value(1))はinvoke()メソッドによって参照される.
prepareを実行した後、私たちはもう一度このリストを巡り、executeメソッドを1つずつ実行し、executeメソッドを実行した後、バイトコードを生成しました.
チュートリアルが始まる前に、まず操作を生成するバイトコードコマンドの原理を簡単に紹介します.Javaコードの中で私たちの最も基本的な演算は操作であることを知っています.例えば、4つの演算、方法呼び出しなど、コードなどです.
String a = "str";
int i = 1 + 2;
i++;
System.out.println(a + i);
ここには6種類の操作があります.
1.String a = "str";
= :
2.int i = 1 + 2;
+ :
= :
3.i++;
++ :
4 System.out.println(a + i);
_ "." :
+ :
操作である以上操作因子がありますが、操作因子とは何ですか?次の表を参照してください.
コード#コード#
オペレーションファクタ
String a = "str";
"str"
int i = 1 + 2;
1, 2, 1+2
i++;
i
System.out.println(a + i)
a, i, a + 1
全部で10種類の操作が存在し、具体的には以下の通りである(ここでは各操作の1つのみを列挙し、すべて列挙しない).
1. String a = "str"; =:割り当て
2. i++;++:インクリメンタル操作
3. int i = 1 + 2; +:演算演算演算=:代入
4.9&7&:ビット操作
5.a>1>:関係演算操作
6.true&&false&&:論理演算操作7.k = i < 0 ? -i : i _さんげんそうさ
8.a instanceof String instanceof:instanceof操作9."Hello "+ "asmsupport!"+:文字列の結合操作10.System.out.println(a + i); _2番目".":メソッド呼び出しアクション
私たちのプログラムでは、すべての操作をIBlockOperatorsのメソッド呼び出しで実現します.すべての操作因子はメソッドパラメータによって伝達される.また,ある操作は同様に他の操作の操作因子とすることができ,上記の1+2が付与操作"="としての操作因子である.asmsupportではjwを継承する限り.asmsupport.Parameterizedインタフェースは、いずれも操作因子として使用できます.実はasmsupportを使用する場合、javaコードで操作因子として使用できるのはasmsupportでも操作因子として使用できるのがほとんどです.asmsupportはjavaコードの作成方法を保持しているからです.ここではASMSupportを使ったアングルでご紹介します.
ここでは、これらの操作が最下位でどのように実現されているかを簡単に説明します.ASMSupportではjava操作をクラスAbstractOperatorとして抽象化する.class、各具体的な操作はそれから継承されています.例えばinstanceof操作はjwに抽象化します.asmsupport.operators.InstanceofOperator.AbstraactOperatorはjwも継承する.asmsupport.Executeableインタフェースです.このインタフェースには2つの方法があります.
各操作はExecuteableインタフェースに相当します.ASMSupportは、各対応するExecuteableを1つのListで所望のコードの順序でこのListに格納します(実行キューにはプログラムブロックjw.asmsupport.block.ProgramBlockも格納します).すべての操作を実行キューに格納した後、すべての操作を巡回し、すべての操作に対してprepareメソッドを実行し、再び実行キューを巡回します.各要素に対してexecuteメソッドを実行します.prepareメソッドの役割は実行キューを統合し再配置することであり,executeメソッドはバイトコード命令を生成することである.たとえば、次のコードを生成します.
int value = 100 + 10;
System.out.println(value + 1);
ASMSupportで生成されたこのコードは次のとおりです.
LocalVariable value = createVariable("value", AClass.INT_ACLASS, false, this.add(Value.value(100), Value.value(10)));
invoke(AClassFactory.getProductClass(System.class).getGlobalVariable("out"), "println", add(value, Value.value(1)));
私たちはそれぞれ100,10,1をValueを通過することを見ることができます.value()メソッドは、対応するjwを生成する.asmsupport.definition.value.Valueオブジェクト.addメソッドはjwを返す.asmsupport.operators.numerical.arithmetic.Additionオブジェクト、createVariableメソッドはjwを返します.asmsupport.definition.variable.LocalVariableオブジェクト、invokeメソッドはjwを返します.asmsupport.operators.method.MethodInvoker.私はリスト形式ですべてのオブジェクトが作成された順序をリストします.順序は一番上の最初の作成です.
シーケンス番号
ASMSupportコード
結果タイプを返す
対応javaコード
1
Value.value(100)
jw.asmsupport.definition.value.Value
数値100
2
Value.value(10)
jw.asmsupport.definition.value.Value
数値10
3
this.add()
jw.asmsupport.operators.numerical.arithmetic.Addition
加算操作(100+10)
4
createVariable()
jw.asmsupport.definition.variable.LocalVariable
変数を作成し、上記の加算操作の結果をこの変数valueに格納します.ここではLocalVariableを返すが、このコードを実行するときも内部にjwが作成される.asmsupport.operators.variable.LocalVariableCreatorオブジェクトとjw.asmsupport.operators.assign.Assignerオブジェクトは、JVMレベルでメソッドのローカル変数に変数を登録する役割を果たす変数を作成します.
5
...getGlobalVariable("out")
jw.asmsupport.definition.variable.GlobalVariable
システムを取得します.out
6
Value.value(1)
jw.asmsupport.definition.value.Value
数値1
7
add(value, Value.value(1))
jw.asmsupport.operators.numerical.arithmetic.Addition
加算アクション:value+1
8
invoke(...)
jw.asmsupport.operators.method.MethodInvoker
メソッド呼び出し操作は、1番目のパラメータがメソッドの所有者である、メソッド名が2番目のパラメータであり、残りのパラメータが呼び出すメソッドのパラメータを表し、ここでSystemを表す.out.println(value + 1)
上記の手順に従って実行が完了すると、ASMSupportは、上記で作成したExecuteableタイプのオブジェクト(可視ソースコード:jw.asmsupport.block.ProgramBlockのexecuteQueue)を実行キュー(Listタイプ)で保存し、ソースコードによって、すべてのブロックProgramBlockおよびそのサブクラス、すべての操作(AbstraactOperatorのサブクラス)、グローバル変数操作GlobalVariableCreatorとメソッドを作成するMethodCreatorはExecuteableのメソッドを実現しています.次のような実行キューが得られます.
オブジェクト
別名#ベツメイ#
対応コード
Addition
add1
100 + 10
LocalVariableCreator
Assigner
ass1
Addition
add2
MethodInvoker
mi
System.out.println(...)
他のオブジェクトについては、コードを通じて、Valueのような対応する操作クラスに転送されていることがわかります.value(100)とValue.value(10)はadd 1に伝わった.すべてのオブジェクトがセットされた後、prepareメソッドが1つずつ実行されると、実行後の実行キューは次のようになります.
オブジェクト
別名#ベツメイ#
対応コード
Assigner
ass1
value = add1
MethodInvoker
mi
System.out.println(...);
なぜprepareが実行された後に実行キューがadd 1,add 2を除去するのかというと、prepareがこのキューを巡ったときに各キュー内のオブジェクトに対して判断されると他のオブジェクトに参照され、他の参照されると削除され、executeメソッドを実行する制御権が参照されるオブジェクトに渡されるからである.プログラムはどのように他の操作に引用されたかを判断するか,ParameterizedインタフェースのasArgument()メソッドを通過する.コードでthisが見えます.add(Value.value(100), Value.value(10))このコードの戻り値はcreateVariableメソッドによって参照される.add(value,Value.value(1))はinvoke()メソッドによって参照される.
prepareを実行した後、私たちはもう一度このリストを巡り、executeメソッドを1つずつ実行し、executeメソッドを実行した後、バイトコードを生成しました.