下面列出了怎么用org.objectweb.asm.tree.analysis.Frame的API类实例代码及写法,或者点击链接到github查看源代码。
private InsnList processFieldSet(MethodNode methodNode, Frame<AbstractValue>[] frames, Map<AbstractInsnNode, InsnList> patches, FieldInsnNode fieldInsnNode) {
InsnList proxyArgumentFix = new InsnList();
Frame<AbstractValue> frame = frames[methodNode.instructions.indexOf(fieldInsnNode)];
Type type = Type.getType(fieldInsnNode.desc);
AbstractValue argumentValue = frame.getStack(frame.getStackSize() - 1);
if (argumentValue.isConstant() && argumentValue.getUsages().size() == 1) {
AbstractInsnNode valueInsn = ejectorContext.isJunkArguments() ? ASMUtils.getRandomValue(type) : ASMUtils.getDefaultValue(type);
patches.put(argumentValue.getInsnNode(), ASMUtils.singletonList(valueInsn));
if (fieldInsnNode.getOpcode() != PUTSTATIC) {
proxyArgumentFix.add(new VarInsnNode(ALOAD, 0));
proxyArgumentFix.add(new TypeInsnNode(CHECKCAST, fieldInsnNode.owner));
}
proxyArgumentFix.add(argumentValue.getInsnNode().clone(null));
proxyArgumentFix.add(fieldInsnNode.clone(null));
}
return proxyArgumentFix;
}
private void processClass(ClassWrapper classWrapper, AtomicInteger counter) {
new ArrayList<>(classWrapper.getMethods()).stream()
.filter(methodWrapper -> !excluded(methodWrapper))
.filter(methodWrapper -> !"<init>".equals(methodWrapper.getMethodNode().name))
.forEach(methodWrapper -> {
EjectorContext ejectorContext = new EjectorContext(counter, classWrapper, junkArguments, junkArgumentStrength);
getPhases(ejectorContext).forEach(ejectPhase -> {
ConstantAnalyzer constantAnalyzer = new ConstantAnalyzer();
try {
Main.info("Analyze: " + classWrapper.getOriginalName() + "::" + methodWrapper.getOriginalName() + methodWrapper.getOriginalDescription());
Frame<AbstractValue>[] frames = constantAnalyzer.analyze(classWrapper.getName(), methodWrapper.getMethodNode());
ejectPhase.process(methodWrapper, frames);
} catch (AnalyzerException e) {
Main.severe("Can't analyze method: " + classWrapper.getOriginalName() + "::" + methodWrapper.getOriginalName() + methodWrapper.getOriginalDescription());
Main.severe(e.toString());
}
});
});
}
@Test
public void testCompilerGeneratedStringBuilder() {
String part1 = "Hello";
String part2 = "World";
Frame<AbstractValue>[] frames = getFrames(parse(
"A:\n" +
"LDC \""+ part1 + "\"\n" +
"ASTORE s\n" +
"NEW java/lang/StringBuilder\n" +
"DUP\n" +
"INVOKESPECIAL java/lang/StringBuilder.<init>()V\n" +
"ALOAD s\n" +
"INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;\n" +
"LDC \""+ part2 + "\"\n" +
"INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;\n" +
"INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;\n" +
"ASTORE s\n" +
"RETURN"));
assertEquals(part1 + part2, frames[frames.length - 2].getStack(0).getValue());
}
@Test
public void testManualStringBuilder() {
String part1 = "Hello";
String part2 = "World";
Frame<AbstractValue>[] frames = getFrames(parse(
"A:\n" +
"NEW java/lang/StringBuilder\n" +
"DUP\n" +
"INVOKESPECIAL java/lang/StringBuilder.<init>()V\n" +
"ASTORE sb\n" +
"B:\n" +
"ALOAD sb\n" +
"LDC \""+ part1 + "\"\n" +
"INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;\n" +
"LDC \""+ part2 + "\"\n" +
"INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;\n" +
"POP\n" +
"ALOAD sb\n" +
"INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;\n" +
"ASTORE str\n" +
"RETURN"));
SimulatedVirtualValue retFrameLocal = (SimulatedVirtualValue) frames[frames.length - 2].getLocal(1);
assertEquals(part1 + part2, retFrameLocal.getValue());
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void removeDeadCode(ClassNode cn, MethodNode mn) {
Analyzer analyzer = new Analyzer(new BasicInterpreter());
try {
analyzer.analyze(cn.name, mn);
} catch (AnalyzerException e) {
ErrorDisplay.error("Could not analyze the code: " + e.getMessage());
return;
}
Frame[] frames = analyzer.getFrames();
AbstractInsnNode[] insns = mn.instructions.toArray();
for (int i = 0; i < frames.length; i++) {
AbstractInsnNode insn = insns[i];
if (frames[i] == null && insn.getType() != AbstractInsnNode.LABEL) {
mn.instructions.remove(insn);
insns[i] = null;
}
}
}
/**
* Copy constructor.
*
* @param src the frame being copied
*/
@SuppressWarnings("unchecked")
public AssignmentTrackingFrame(Frame<? extends V> src) {
super(src);
AssignmentTrackingFrame trackingFrame = (AssignmentTrackingFrame) src;
localVariablesSet = new ArrayDeque<>();
for (Set<Integer> integers : (Deque<Set<Integer>>) trackingFrame.localVariablesSet) {
localVariablesSet.addFirst(new HashSet<>(integers));
}
labelsStack = new ArrayDeque<>(trackingFrame.labelsStack);
}
static void printAnalyzerResult(
final MethodNode method, final Analyzer<BasicValue> analyzer, final PrintWriter printWriter) {
Textifier textifier = new Textifier();
TraceMethodVisitor traceMethodVisitor = new TraceMethodVisitor(textifier);
printWriter.println(method.name + method.desc);
for (int i = 0; i < method.instructions.size(); ++i) {
method.instructions.get(i).accept(traceMethodVisitor);
StringBuilder stringBuilder = new StringBuilder();
Frame<BasicValue> frame = analyzer.getFrames()[i];
if (frame == null) {
stringBuilder.append('?');
} else {
for (int j = 0; j < frame.getLocals(); ++j) {
stringBuilder.append(getUnqualifiedName(frame.getLocal(j).toString())).append(' ');
}
stringBuilder.append(" : ");
for (int j = 0; j < frame.getStackSize(); ++j) {
stringBuilder.append(getUnqualifiedName(frame.getStack(j).toString())).append(' ');
}
}
while (stringBuilder.length() < method.maxStack + method.maxLocals + 1) {
stringBuilder.append(' ');
}
printWriter.print(Integer.toString(i + 100000).substring(1));
printWriter.print(
" " + stringBuilder + " : " + textifier.text.get(textifier.text.size() - 1));
}
for (TryCatchBlockNode tryCatchBlock : method.tryCatchBlocks) {
tryCatchBlock.accept(traceMethodVisitor);
printWriter.print(" " + textifier.text.get(textifier.text.size() - 1));
}
printWriter.println();
}
public boolean isThisTargetOfGet(int index) {
Frame<ConstructorThisInterpreter.ThisValue> frame = this.frames[index];
// Note that we will treat this as safe, even on invalid bytecode (we handle the stack underflow).
int size = frame.getStackSize();
return (size > 0)
? frame.getStack(size - 1).isThis
: false;
}
public boolean isThisTargetOfPut(int index) {
Frame<ConstructorThisInterpreter.ThisValue> frame = this.frames[index];
// Note that we will treat this as safe, even on invalid bytecode (we handle the stack underflow).
int size = frame.getStackSize();
return (size > 1)
? frame.getStack(size - 2).isThis
: false;
}
@Test
public void testEmptyStack() throws Exception {
@SuppressWarnings("unchecked")
Frame<ConstructorThisInterpreter.ThisValue>[] frames = new Frame[] {
new Frame<ConstructorThisInterpreter.ThisValue>(LOCAL_COUNT, 0)
};
StackThisTracker tracker = new StackThisTracker(frames);
Assert.assertFalse(tracker.isThisTargetOfGet(0));
Assert.assertFalse(tracker.isThisTargetOfPut(0));
Assert.assertEquals(frames.length, tracker.getFrameCount());
}
@Test
public void testPartialStack() throws Exception {
Frame<ConstructorThisInterpreter.ThisValue> frame = new Frame<>(LOCAL_COUNT, 1);
frame.push(ConstructorThisInterpreter.ThisValue.createNotThis(BasicValue.REFERENCE_VALUE));
@SuppressWarnings("unchecked")
Frame<ConstructorThisInterpreter.ThisValue>[] frames = new Frame[] {
frame
};
StackThisTracker tracker = new StackThisTracker(frames);
Assert.assertFalse(tracker.isThisTargetOfGet(0));
Assert.assertFalse(tracker.isThisTargetOfPut(0));
}
@Test
public void testGet() throws Exception {
Frame<ConstructorThisInterpreter.ThisValue> frame = new Frame<>(LOCAL_COUNT, 4);
frame.push(ConstructorThisInterpreter.ThisValue.createNotThis(BasicValue.REFERENCE_VALUE));
frame.push(ConstructorThisInterpreter.ThisValue.createNotThis(BasicValue.REFERENCE_VALUE));
frame.push(ConstructorThisInterpreter.ThisValue.createNotThis(BasicValue.REFERENCE_VALUE));
frame.push(ConstructorThisInterpreter.ThisValue.createThis(BasicValue.REFERENCE_VALUE));
@SuppressWarnings("unchecked")
Frame<ConstructorThisInterpreter.ThisValue>[] frames = new Frame[] {
frame
};
StackThisTracker tracker = new StackThisTracker(frames);
Assert.assertTrue(tracker.isThisTargetOfGet(0));
Assert.assertFalse(tracker.isThisTargetOfPut(0));
}
@Test
public void testPut() throws Exception {
Frame<ConstructorThisInterpreter.ThisValue> frame = new Frame<>(LOCAL_COUNT, 4);
frame.push(ConstructorThisInterpreter.ThisValue.createNotThis(BasicValue.REFERENCE_VALUE));
frame.push(ConstructorThisInterpreter.ThisValue.createNotThis(BasicValue.REFERENCE_VALUE));
frame.push(ConstructorThisInterpreter.ThisValue.createThis(BasicValue.REFERENCE_VALUE));
frame.push(ConstructorThisInterpreter.ThisValue.createNotThis(BasicValue.REFERENCE_VALUE));
@SuppressWarnings("unchecked")
Frame<ConstructorThisInterpreter.ThisValue>[] frames = new Frame[] {
frame
};
StackThisTracker tracker = new StackThisTracker(frames);
Assert.assertFalse(tracker.isThisTargetOfGet(0));
Assert.assertTrue(tracker.isThisTargetOfPut(0));
}
private static Map<FieldSetInfo, List<FieldInsnNode>> analyzeFieldSets(MethodNode methodNode, Frame<AbstractValue>[] frames) {
Map<FieldSetInfo, List<FieldInsnNode>> result = new HashMap<>();
InsnList insnList = methodNode.instructions;
ListIterator<AbstractInsnNode> iterator = insnList.iterator();
while (iterator.hasNext()) {
AbstractInsnNode abstractInsnNode = iterator.next();
if (!(abstractInsnNode instanceof FieldInsnNode))
continue;
FieldInsnNode fieldInsnNode = (FieldInsnNode) abstractInsnNode;
if (fieldInsnNode.getOpcode() != PUTFIELD && fieldInsnNode.getOpcode() != PUTSTATIC)
continue;
Frame<AbstractValue> frame = frames[insnList.indexOf(fieldInsnNode)];
AbstractValue value = frame.getStack(frame.getStackSize() - 1);
if (!value.isConstant())
continue;
FieldSetInfo fieldSetInfo = new FieldSetInfo(fieldInsnNode.getOpcode(), fieldInsnNode.desc);
if (!result.containsKey(fieldSetInfo)) {
ArrayList<FieldInsnNode> list = new ArrayList<>();
list.add(fieldInsnNode);
result.put(fieldSetInfo, list);
} else {
result.get(fieldSetInfo).add(fieldInsnNode);
}
}
return result;
}
private static Map<MethodCallInfo, List<MethodInsnNode>> analyzeMethodCalls(MethodNode methodNode, Frame<AbstractValue>[] frames) {
Map<MethodCallInfo, List<MethodInsnNode>> result = new HashMap<>();
InsnList insnList = methodNode.instructions;
ListIterator<AbstractInsnNode> iterator = insnList.iterator();
while (iterator.hasNext()) {
AbstractInsnNode abstractInsnNode = iterator.next();
if (!(abstractInsnNode instanceof MethodInsnNode))
continue;
MethodInsnNode methodInsnNode = (MethodInsnNode) abstractInsnNode;
if ("<init>".equals(methodInsnNode.name))
continue;
Type[] argumentTypes = Type.getArgumentTypes(methodInsnNode.desc);
if (argumentTypes.length == 0)
continue;
int constantArguments = 0;
Frame<AbstractValue> frame = frames[insnList.indexOf(methodInsnNode)];
for (int i = 0; i < argumentTypes.length; i++) {
AbstractValue value = frame.getStack(frame.getStackSize() - argumentTypes.length + i);
if (value.isConstant() && value.getUsages().size() == 1)
constantArguments++;
}
if (constantArguments == 0)
continue;
MethodCallInfo methodCallInfo = new MethodCallInfo(methodInsnNode.owner, methodInsnNode.itf, methodInsnNode.getOpcode(), methodInsnNode.name, methodInsnNode.desc);
if (!result.containsKey(methodCallInfo)) {
ArrayList<MethodInsnNode> list = new ArrayList<>();
list.add(methodInsnNode);
result.put(methodCallInfo, list);
} else {
result.get(methodCallInfo).add(methodInsnNode);
}
}
return result;
}
private void update() {
// No valid instruction was found
if (insnIndex == -1)
return;
// Skip if no prior compile
if (assembler.getLastCompile() == null)
return;
// Skip abstract methods
if (AccessFlag.isAbstract(assembler.getLastCompile().access))
return;
Frame<AbstractValue>[] frames = getFrames();
if (frames == null) {
if (isVerifyDisabled()) {
// TODO: Warn user that verification is disabled. Enable it for more information.
return;
} else {
Log.error(new IllegalStateException(),
"Stack helper tried to display frames despite the method being non-verifiable.");
return;
}
}
if (insnIndex >= frames.length)
return;
// Update lists
currentFrame = frames[insnIndex];
Platform.runLater(() -> {
locals.getItems().clear();
stack.getItems().clear();
if (currentFrame != null) {
for (int i = 0; i < currentFrame.getLocals(); i++)
locals.getItems().add(i);
for (int i = 0; i < currentFrame.getStackSize(); i++)
stack.getItems().add(i);
}
});
}
/**
* @return Method frames.
*/
private Frame<AbstractValue>[] getFrames() {
Frame<AbstractValue>[] frames = assembler.getFrames();
if (frames == null && isVerifyDisabled()) {
// Generate the frames since the assembler didn't.
try {
MethodAnalyzer analyzer = new MethodAnalyzer(new SimInterpreter());
analyzer.setSkipDeadCodeBlocks(false);
frames = analyzer.analyze(assembler.getDeclaringType(), assembler.getLastCompile());
} catch(Throwable t) {
// We will allow failures. Users should enable verification for more information.
}
}
return frames;
}
@Test
public void testStaticMathCall() {
int large = 20;
int small = 5;
Frame<AbstractValue>[] frames = getFrames(parse(
"A:\n" +
"BIPUSH " + large + "\n" +
"BIPUSH " + small + "\n" +
"INVOKESTATIC java/lang/Math.min(II)I\n" +
"ISTORE 0\n" +
"B:\n" +
"RETURN"));
assertEquals(small, frames[frames.length - 2].getLocal(0).getValue());
}
@Test
public void testStringLength() {
String str = "1234567";
Frame<AbstractValue>[] frames = getFrames(parse(
"A:\n" +
"LDC \"" + str + "\"\n" +
"INVOKEVIRTUAL java/lang/String.length()I\n" +
"ISTORE 0\n" +
"B:\n" +
"RETURN"));
assertEquals(str, frames[3].getStack(0).getValue());
assertEquals(str.length(), frames[4].getStack(0).getValue());
}
@Test
public void testDontMergeWhenScopeChanges() {
String initial = "INIT";
String one = "PATH_A";
String two = "PATH_B";
Frame<AbstractValue>[] frames = getFrames(parse(
"NEW java/lang/StringBuilder\n" +
"DUP\n" +
"LDC \""+ initial + "\"\n" +
"INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V\n" +
"ASTORE sb\n" +
"B:\n" +
"INVOKESTATIC MyClass.someBool()Z\n" +
"IFEQ D\n" +
"C:\n" +
"ALOAD sb\n" +
"LDC \""+ one + "\"\n" +
"INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;\n" +
"GOTO E\n" +
"D:\n" +
"ALOAD sb\n" +
"LDC \""+ two + "\"\n" +
"INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;\n" +
"E:\n" +
"ALOAD sb\n" +
"INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;\n" +
"INVOKESTATIC Logger.print(Ljava/lang/String;)V\n" +
"RETURN"));
SimulatedVirtualValue retFrameLocal = (SimulatedVirtualValue) frames[frames.length - 2].getLocal(0);
assertFalse(retFrameLocal.isNull());
assertFalse(retFrameLocal.isValueUnresolved());
assertNotEquals(initial, retFrameLocal.getValue());
assertNotEquals(one, retFrameLocal.getValue());
assertNotEquals(two, retFrameLocal.getValue());
}
@Test
@Disabled
// TODO: Manage opaque predicates
public void testMergeWithOpaquePredicate() {
String initial = "INIT";
String one = "PATH_A";
String two = "PATH_B";
Frame<AbstractValue>[] frames = getFrames(parse(
"NEW java/lang/StringBuilder\n" +
"DUP\n" +
"LDC \""+ initial + "\"\n" +
"INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V\n" +
"ASTORE sb\n" +
"B:\n" +
"ICONST_0\n" +
"IFEQ D\n" +
"C:\n" +
"ALOAD sb\n" +
"LDC \""+ one + "\"\n" +
"INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;\n" +
"GOTO E\n" +
"D:\n" +
"ALOAD sb\n" +
"LDC \""+ two + "\"\n" +
"INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;\n" +
"E:\n" +
"ALOAD sb\n" +
"INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;\n" +
"INVOKESTATIC Logger.print(Ljava/lang/String;)V\n" +
"RETURN"));
SimulatedVirtualValue retFrameLocal = (SimulatedVirtualValue) frames[frames.length - 2].getLocal(0);
assertFalse(retFrameLocal.isNull());
assertFalse(retFrameLocal.isValueUnresolved());
assertNotEquals(initial, retFrameLocal.getValue());
assertNotEquals(one, retFrameLocal.getValue());
assertEquals(two, retFrameLocal.getValue());
}
static void printAnalyzerResult(MethodNode method, Analyzer<BasicValue> a, final PrintWriter pw) {
Frame<BasicValue>[] frames = a.getFrames();
Textifier t = new Textifier();
TraceMethodVisitor mv = new TraceMethodVisitor(t);
pw.println(method.name + method.desc);
for (int j = 0; j < method.instructions.size(); ++j) {
method.instructions.get(j).accept(mv);
StringBuilder sb = new StringBuilder();
Frame<BasicValue> f = frames[j];
if (f == null) {
sb.append('?');
} else {
for (int k = 0; k < f.getLocals(); ++k) {
sb.append(getShortName(f.getLocal(k).toString())).append(' ');
}
sb.append(" : ");
for (int k = 0; k < f.getStackSize(); ++k) {
sb.append(getShortName(f.getStack(k).toString())).append(' ');
}
}
while (sb.length() < method.maxStack + method.maxLocals + 1) {
sb.append(' ');
}
pw.print(Integer.toString(j + 100000).substring(1));
pw.print(" " + sb + " : " + t.text.get(t.text.size() - 1));
}
for (int j = 0; j < method.tryCatchBlocks.size(); ++j) {
method.tryCatchBlocks.get(j).accept(mv);
pw.print(" " + t.text.get(t.text.size() - 1));
}
pw.println();
}
private AbstractInsnNode getSource(MethodNode methodNode, Frame<SourceValue>[] frames, AbstractInsnNode now, int... wants) {
Frame<SourceValue> currentFrame = frames[methodNode.instructions.indexOf(now)];
SourceValue currentValue;
for (int want : wants)
if (want == now.getOpcode()) return now;
switch (now.getOpcode()) {
case ALOAD: {
currentValue = currentFrame.getLocal(((VarInsnNode) now).var);
break;
}
case ASTORE: {
currentValue = currentFrame.getStack(currentFrame.getStackSize() - 1);
break;
}
case DUP: {
currentValue = currentFrame.getStack(currentFrame.getStackSize() - 1);
break;
}
case PUTSTATIC: {
currentValue = currentFrame.getStack(currentFrame.getStackSize() - 1);
break;
}
case SWAP: {
currentValue = currentFrame.getStack(currentFrame.getStackSize() - 1);
break;
}
default: {
oops("Unexpected opcode {}", now.getOpcode());
return null;
}
}
if (currentValue.insns.size() != 1) {
oops("Expected 1 source insn, found {}", TransformerHelper.insnsToString(currentValue.insns));
return null;
}
return getSource(methodNode, frames, currentValue.insns.iterator().next(), wants);
}
static void printAnalyzerResult(
final MethodNode method, final Analyzer<BasicValue> analyzer, final PrintWriter printWriter) {
Textifier textifier = new Textifier();
TraceMethodVisitor traceMethodVisitor = new TraceMethodVisitor(textifier);
printWriter.println(method.name + method.desc);
for (int i = 0; i < method.instructions.size(); ++i) {
method.instructions.get(i).accept(traceMethodVisitor);
StringBuilder stringBuilder = new StringBuilder();
Frame<BasicValue> frame = analyzer.getFrames()[i];
if (frame == null) {
stringBuilder.append('?');
} else {
for (int j = 0; j < frame.getLocals(); ++j) {
stringBuilder.append(getUnqualifiedName(frame.getLocal(j).toString())).append(' ');
}
stringBuilder.append(" : ");
for (int j = 0; j < frame.getStackSize(); ++j) {
stringBuilder.append(getUnqualifiedName(frame.getStack(j).toString())).append(' ');
}
}
while (stringBuilder.length() < method.maxStack + method.maxLocals + 1) {
stringBuilder.append(' ');
}
printWriter.print(Integer.toString(i + 100000).substring(1));
printWriter.print(
" " + stringBuilder + " : " + textifier.text.get(textifier.text.size() - 1));
}
for (TryCatchBlockNode tryCatchBlock : method.tryCatchBlocks) {
tryCatchBlock.accept(traceMethodVisitor);
printWriter.print(" " + textifier.text.get(textifier.text.size() - 1));
}
printWriter.println();
}
static void printAnalyzerResult(
final MethodNode method, final Analyzer<BasicValue> analyzer, final PrintWriter printWriter) {
Textifier textifier = new Textifier();
TraceMethodVisitor traceMethodVisitor = new TraceMethodVisitor(textifier);
printWriter.println(method.name + method.desc);
for (int i = 0; i < method.instructions.size(); ++i) {
method.instructions.get(i).accept(traceMethodVisitor);
StringBuilder stringBuilder = new StringBuilder();
Frame<BasicValue> frame = analyzer.getFrames()[i];
if (frame == null) {
stringBuilder.append('?');
} else {
for (int j = 0; j < frame.getLocals(); ++j) {
stringBuilder.append(getUnqualifiedName(frame.getLocal(j).toString())).append(' ');
}
stringBuilder.append(" : ");
for (int j = 0; j < frame.getStackSize(); ++j) {
stringBuilder.append(getUnqualifiedName(frame.getStack(j).toString())).append(' ');
}
}
while (stringBuilder.length() < method.maxStack + method.maxLocals + 1) {
stringBuilder.append(' ');
}
printWriter.print(Integer.toString(i + 100000).substring(1));
printWriter.print(
" " + stringBuilder + " : " + textifier.text.get(textifier.text.size() - 1));
}
for (TryCatchBlockNode tryCatchBlock : method.tryCatchBlocks) {
tryCatchBlock.accept(traceMethodVisitor);
printWriter.print(" " + textifier.text.get(textifier.text.size() - 1));
}
printWriter.println();
}
SuspendContinuationPoint(
Integer lineNumber,
MethodInsnNode invokeInstruction,
Frame<BasicValue> frame) {
// lineNumber is null if it doesn't exist
Validate.notNull(invokeInstruction);
// stateModifierMethod is null if it doesn't exist
Validate.notNull(frame);
this.lineNumber = lineNumber;
this.invokeInstruction = invokeInstruction;
this.continueExecutionLabel = new LabelNode();
this.frame = frame;
}
TryCatchInvokeContinuationPoint(
Integer lineNumber,
MethodInsnNode invokeInstruction,
Frame<BasicValue> frame) {
// lineNumber is null if it doesn't exist
Validate.notNull(invokeInstruction);
Validate.notNull(frame);
this.lineNumber = lineNumber;
this.invokeInstruction = invokeInstruction;
this.continueExecutionLabel = new LabelNode();
this.exceptionExecutionLabel = new LabelNode();
this.tryCatchBlock = new TryCatchBlockNode(null, null, null, null);
this.frame = frame;
}
SynchronizationPoint(
InsnNode monitorInstruction,
Frame<BasicValue> frame) {
Validate.notNull(monitorInstruction);
Validate.notNull(frame);
Validate.isTrue(monitorInstruction.getOpcode() == Opcodes.MONITORENTER || monitorInstruction.getOpcode() == Opcodes.MONITOREXIT);
this.monitorInstruction = monitorInstruction;
this.frame = frame;
}
NormalInvokeContinuationPoint(
Integer lineNumber,
MethodInsnNode invokeInstruction,
Frame<BasicValue> frame) {
// lineNumber is null if it doesn't exist
Validate.notNull(invokeInstruction);
// stateModifierMethod is null if it doesn't exist
Validate.notNull(frame);
this.lineNumber = lineNumber;
this.invokeInstruction = invokeInstruction;
this.continueExecutionLabel = new LabelNode();
this.frame = frame;
}
@Override
public Frame init(Frame frame) {
super.init(frame);
if (frame instanceof MonitoringFrame) {
monitored = new LinkedList<Integer>(MonitoringFrame.class.cast(frame).monitored);
} else {
monitored = new LinkedList<Integer>();
}
return this;
}