我正在生成一個簡單的類並且無法注入一個適當的變量名稱。 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
}
我使用newLocal()
呼叫visitLocalVariable()
提供相同的變量指標。但是在字節碼映射索引中是3
而不是1
。如果變量具有「較短」類型,例如int
,那麼該索引應該是2
,而仍然不是1
。
從我的觀察,這是因爲以下原因。 LocalVariablesSorter
維護從舊變量索引到新變量的映射。它也覆蓋方法visitLocalVariable
,並且在將訪問權委託給訪問者鏈之前,它從映射中計算出newIndex
。 newIndex
通過另一種私人方法remap()
進行計算。該方法檢查給定變量是否已存在映射,如果沒有,則創建新映射。我看到的問題是,newLocal()
方法不會在映射中添加任何內容。
而且我可以從ASM源看到storeInsn()
在GeneratorAdapter
代表visitVarInsn()
改爲調用環比下跌調用的LocalVariablesSorter
實施。因爲它在LocalVariablesSorter
實現中,所以爲變量索引調用remap()
方法並更新映射。
所以我的問題是如何使用GeneratorAdapter
所以變量在發出字節碼正確命名或如何GeneratorAdapter
與LocalVariablesSorter
鏈中,使他們正常工作結合起來?
好吧,它是'LocalVariablesSorter'的*用途*,用於修改後續'visit ...'調用的行爲。顯然,所有不應該改變的操作必須繞過'LocalVariablesSorter',就像'GeneratorAdapter'引入的方法一樣。 – Holger
那麼爲什麼GeneratorAdapter從LocalVariablesSorter繼承,如果它無法提供父代的功能呢? – alllex
不要問我,我不是那個做出這個決定的人。但是,在目標訪問者而不是適配器上調用該方法的問題在哪裏? – Holger