【发布时间】:2012-11-27 17:38:50
【问题描述】:
我正在尝试使用 ASM 修补一个类。我需要在函数中添加一些逻辑。这个逻辑需要一个新的局部变量。这是我所做的:
class CreateHashTableMethodAdapter extends MethodAdapter {
@Override
public void visitMethodInsn(int opcode, String owner,String name, String desc){
System.out.println(opcode + "/" + owner + "/" + name + "/" + desc);
if(opcode == Opcodes.INVOKESPECIAL &&
"javax/naming/InitialContext".equals(owner) &&
"<init>".equals(name) &&
"()V".equals(desc)){
System.out.println("In mod");
// 83: new #436; //class javax/naming/InitialContext
// 86: dup
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "javax/naming/InitialContext", "<init>", "()V");
mv.visitVarInsn(Opcodes.ASTORE, 1);
Label start_patch = new Label();
Label end_patch = new Label();
mv.visitLabel(start_patch);
mv.visitTypeInsn(Opcodes.NEW,"java/util/Hashtable");
mv.visitInsn(Opcodes.DUP);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/Hashtable", "<init>", "()V");
mv.visitVarInsn(Opcodes.ASTORE,9);
// ........ sNip ..........
mv.visitLabel(end_patch);
mv.visitLocalVariable("env","Ljava/util/Hashtable;",null,start_patch,end_patch,9);
// 127: astore_1
}
else {
mv.visitMethodInsn(opcode, owner, name, desc);
}
}
}
当我针对CheckClassAdapter 运行此方法适配器时,它指出:
org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 51: Trying to access an inexistant local variable 9
.... sNiP ....
00050 R R . . . : R R : INVOKESPECIAL java/util/Hashtable.<init> ()V
00051 R R . . . : R : ASTORE 9
我认为我滥用了 visitLocalVariable,但我不知道应该在哪里调用它。
当我 javap 生成字节码(不检查)时,我得到以下局部变量表:
LocalVariableTable:
Start Length Slot Name Signature
91 40 9 env Ljava/util/Hashtable;
0 343 0 this Lpmu/jms/ServerJMS;
132 146 1 initialContext Ljavax/naming/InitialContext;
153 125 2 topicConnectionFactory Ljavax/jms/TopicConnectionFactory;
223 55 3 topic Ljavax/jms/Topic;
249 29 4 topicSubscriber Ljavax/jms/TopicSubscriber;
279 55 1 ex Ljava/lang/Exception;
281 53 2 codeMessage I
289 45 3 params Lpmu/data/Parameters;
325 9 4 messageError Ljava/lang/String;
你可能注意到了,我的变量在这里但是最上面?! 有什么想法吗?
【问题讨论】:
-
只有在要生成调试信息时才需要调用 visitLocalVariable。否则可以删除。您发布的异常来自数据流分析器,它不查看调试信息。
-
您在构造 ClassWriter 时是否传递了 ClassWriter.COMPUTE_MAXS,和/或调用
visitMaxs?您需要这样做以更改局部变量表的最大大小。 -
@EugeneKuleshov:好的,我不知道不需要变量声明。那么,我可以假设如果我想使用局部变量,我只需要表足够大吗?
-
@int3 是的,我使用 COMPUTE_MAXS
-
实际上没有任何“表”。使用 COMPUTE_MAXS 标志 ASM 将在 visitMax() 调用中自动计算 maxVars 参数。无论如何,您应该提供一个足以重现您的问题的完整示例。
标签: java variables local bytecode java-bytecode-asm