2017-09-14 90 views
0

Javassist提供编辑代码属性的CodeIterator,该属性可用于横切方法中的所有指令。如何获取JVM指令使用Javassist操作的操作数堆栈上的值?

对于JVM指令时,它总是遵循specification mnemonic operand1 operand2 ... 从二进制组件不同的是,基于堆栈的JVM指令取操作数堆栈上的值。以ifge为例。该指令的格式如下 if<cond> branchbyte1 branchbyte2 ifge成功当且仅当value堆栈≥0时,branchbyte1branchbyte2是跳转的目标。

我的问题是,我可以使用Javassist在操作数堆栈上获得value吗?

+1

该规范没有说“操作数”,它表示“操作数堆栈”。 JVM在规范级有一个基于堆栈的体系结构,并且“操作数”从堆栈中弹出,它之前由前一条指令留下。 –

+0

@ErwinBolwidt感谢澄清。说“从指令使用的操作数堆栈中获取值”是否正确? – Qoros

+0

我宁愿使用ASM来完成这项工作,但无论如何,你的问题还不清楚。在堆栈中有两个操作数和值,但无论哪种情况,您都知道每个指令具有哪些操作数和参数。它写在您链接的规范中... – Holger

回答

0

答案是javassist.bytecode.analysis模块。根据JVM规范,frame用于存储数据和部分结果。每个帧都有自己的局部变量数组,它自己的操作数堆栈以及对运行时常量池的引用。

javassist.bytecode.analysis.FramePrinter中,函数print显示了如何在每条指令处打印每个帧。

/** 
* Prints the instructions and the frame states of the given method. 
*/ 
public void print(CtMethod method) { 
    stream.println("\n" + getMethodString(method)); 
    MethodInfo info = method.getMethodInfo2(); 
    ConstPool pool = info.getConstPool(); 
    CodeAttribute code = info.getCodeAttribute(); 
    if (code == null) 
     return; 

    Frame[] frames; 
    try { 
     frames = (new Analyzer()).analyze(method.getDeclaringClass(), info); 
    } catch (BadBytecode e) { 
     throw new RuntimeException(e); 
    } 

    int spacing = String.valueOf(code.getCodeLength()).length(); 

    CodeIterator iterator = code.iterator(); 
    while (iterator.hasNext()) { 
     int pos; 
     try { 
      pos = iterator.next(); 
     } catch (BadBytecode e) { 
      throw new RuntimeException(e); 
     } 

     stream.println(pos + ": " + InstructionPrinter.instructionString(iterator, pos, pool)); 

     addSpacing(spacing + 3); 
     Frame frame = frames[pos]; 
     if (frame == null) { 
      stream.println("--DEAD CODE--"); 
      continue; 
     } 
     printStack(frame); 

     addSpacing(spacing + 3); 
     printLocals(frame); 
    } 

} 

从这个代码,我们可以看到:

该框架可以通过frames = (new Analyzer()).analyze(method.getDeclaringClass(), info);

注意被收购,这仅返回堆栈项目的类型信息,但它并没有给变量名称。

至于每条指令使用的值,我们应该根据指令的规范对它进行不同的处理。