Javassist Provides the CodeIterator for editing a code attribute, which can be used to transverse all the instructions in the method.
For a JVM instruction, it always follows the specification : mnemonic operand1 operand2 ...
Different from binary assembly, the stack-based JVM instructions takes value on the operand stack. Take the ifge
as an example. The instruction has the following format if<cond> branchbyte1 branchbyte2
ifge succeeds if and only if value
on stack ≥ 0, the branchbyte1
and branchbyte2
are the targets of the jump.
My question is, can I get the value
on the operand stack using Javassist?
The answer is the javassist.bytecode.analysis
module. According the JVM specification, frame
is used to store data and partial results. Each frame has its own array of local variables, its own operand stack, and a reference to the run-time const pool.
In javassist.bytecode.analysis.FramePrinter
, the funciton print
shows how to print for each frame at each instruction.
/**
* 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);
}
}
From this code, we can see:
The frames can be acquired by frames = (new Analyzer()).analyze(method.getDeclaringClass(), info);
NOTE, this only return the type information of the stack item, but it doesn't give variable names.
As for the values each instruction uses, we should treat it differently according to the specification of the instruction.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.