Javassist提供了用于编辑代码属性的CodeIterator,可用于遍历方法中的所有指令。
对于JVM指令,它总是遵循specification:mnemonic operand1 operand2 ...与二进制汇编不同,基于堆栈的JVM指令在操作数堆栈上取值。以ifge为例。当且仅当堆栈if<cond> branchbyte1 branchbyte2 0上的value、branchbyte1和branchbyte2是跳转的目标时,指令的格式如下:≥成功。
我的问题是,我可以使用Javassist获取操作数堆栈上的value吗?
发布于 2017-09-23 05:23:37
答案是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);获取
注意,这只返回堆栈项的类型信息,但不会给出变量名。
至于每条指令使用的值,我们应该根据指令的规范不同地对待它。
https://stackoverflow.com/questions/46208796
复制相似问题