私は単純なクラスを生成しており、適切な変数名を挿入できません。 ASMのバージョンは5.2
です。ここでJava ASM GeneratorAdapter変数名
はコードです:
package com.test;
import org.objectweb.asm.*;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Main {
public static void main(String[] args) throws Exception {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
String name = "com.test.Sub";
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, name.replace('.', '/'), null, "java/lang/Object", null);
Method ctor = Method.getMethod("void <init>()");
GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, ctor, null, null, cw);
mg.visitCode();
mg.loadThis();
mg.invokeConstructor(Type.getType(Object.class), ctor);
int var = mg.newLocal(Type.INT_TYPE);
mg.push(42.42);
mg.storeLocal(var);
Label varLabel = mg.mark();
mg.returnValue();
Label endLabel = mg.mark();
mg.visitLocalVariable("x", "D", null, varLabel, endLabel, var);
mg.endMethod();
cw.visitEnd();
byte[] bytes = cw.toByteArray();
Files.write(Paths.get(name + ".class"), bytes);
}
}
私はコード生成を簡素化するためにGeneratorAdapter
を使用しています。 GeneratorAdapter
はLocalVariablesSorter
から継承されているので、その中からnewLocal(Type)
メソッドを使用することが許可されているものとします。
変数の名前を除いて、発行されるバイトコードに問題はありません。 visitLocalVariable()
メソッドが呼び出されると、変数に名前を代入するのではなく、バイトコードに新しい名前を作成します。
放射されたバイトコード:
// class version 52.0 (52)
// access flags 0x1
public class com/test/Sub {
// access flags 0x1
public <init>()V
ALOAD 0
INVOKESPECIAL java/lang/Object.<init>()V
LDC 42.42
DSTORE 1
L0
RETURN
L1
LOCALVARIABLE x D L0 L1 3
MAXSTACK = 2
MAXLOCALS = 5
}
私はvisitLocalVariable()
にnewLocal()
コールにより提供されたものと同じ変数インデックスを使用しています。しかし、バイトコードマップインデックスでは、1
の代わりに3
です。変数がint
のような「より短い」タイプの場合、インデックスは2
であり、それでも1
ではありません。
私の所見から、これは以下の理由から起こります。 LocalVariablesSorter
は、古い変数インデックスから新しいインデックスへのマッピングを維持します。また、メソッドvisitLocalVariable
をオーバーライドし、呼び出しを訪問者チェーンに委任する前に、マッピングからnewIndex
を計算します。 newIndex
は別のプライベートメソッドremap()
によって計算されます。このメソッドは、指定された変数に対してマッピングがすでに存在するかどうかをチェックし、存在しない場合は新しいマッピングが作成されます。私が見ているように、newLocal()
メソッドはマッピングに何も追加しないという問題があります。
また、私はstoreInsn()
GeneratorAdapter
における代表者visitVarInsn()
コールチェーンダウンの代わりに、LocalVariablesSorter
の実装を呼び出すことASMソースから見ることができます。 LocalVariablesSorter
の実装であるため、可変インデックスに対してremap()
メソッドが呼び出され、マッピングが更新されます。
は、したがって、私の質問はGeneratorAdapter
を使用する方法であるので、変数が放出されたバイトコードまたはそれらがどのように一緒に正常に動作してチェーンにLocalVariablesSorter
でGeneratorAdapter
を組み合わせることで、適切に命名されていますか?
のオブジェクトをそのまま使用することができます。次の 'visit ...'呼び出しの動作を変更するのは、 'LocalVariablesSorter'の*目的*です。明らかに、変更されるべきでないすべての操作は、 'GeneratorAdapter'によって導入されたメソッドのように' LocalVariablesSorter'をバイパスする必要があります。 – Holger
それで 'GeneratorAdapter'が親の機能を提供できない場合、なぜ' LocalVariablesSorter'から継承されるのですか? – alllex
私に尋ねないで、私はこの決定をした人ではない。しかし、アダプターではなくターゲットビジターにそのメソッドを呼び出す際の問題はどこにありますか? – Holger