Java 如何使用ASM创建局部变量?
我正在尝试用ASM修补一个类。我需要在函数中添加一些逻辑。这个逻辑需要一个新的局部变量。以下是我所做的:Java 如何使用ASM创建局部变量?,java,variables,local,bytecode,java-bytecode-asm,Java,Variables,Local,Bytecode,Java Bytecode Asm,我正在尝试用ASM修补一个类。我需要在函数中添加一些逻辑。这个逻辑需要一个新的局部变量。以下是我所做的: class CreateHashTableMethodAdapter extends MethodAdapter { @Override public void visitMethodInsn(int opcode, String owner,String name, String desc){ System.out.println(opcode + "/
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);
}
}
}
我想我误用了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;
您可能注意到,我的变量在这里,但在最上面?!
有什么想法吗?创建新局部变量的一种方便方法是扩展LocalVariablesOrter而不是MethodAdapter。然后,您可以使用
newLocal()
根据需要分配局部变量,而不会干扰现有变量。有关详细信息,请参阅上的ASM 4.0 Java字节码工程库的第3.3.3节。仅当您要生成调试信息时才需要visitLocalVariable调用。否则可以将其删除。您发布的异常来自data flow analyzer,它没有查看调试信息。您在构建ClassWriter时是否传递ClassWriter.COMPUTE_MAXS,和/或调用visitMaxs
?您需要这样做才能更改局部变量表的最大大小。@EugeneKuleshov:好的,我不知道不需要变量声明。那么,我可以假设如果我想使用局部变量,我只需要表足够大吗?@int3是的,我使用COMPUTE\u maxsetre,它实际上不是任何“表”。使用COMPUTE_MAXS标志,ASM将在visitMax()调用中自动计算maxVars参数。无论如何,你应该提供一个完整的例子,足以重现你的问题。
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;