Various bytecode disassembler fixes / additions.

This commit is contained in:
GraxCode 2022-03-18 14:33:39 +01:00
parent 80a3e8b7f0
commit b5b1734302
2 changed files with 332 additions and 326 deletions

View file

@ -1,37 +1,19 @@
package the.bytecode.club.bytecodeviewer.decompilers.bytecode;
import eu.bibl.banalysis.asm.desc.OpcodeInfo;
import org.apache.commons.text.StringEscapeUtils;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.*;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.text.StringEscapeUtils;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.FrameNode;
import org.objectweb.asm.tree.IincInsnNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.LineNumberNode;
import org.objectweb.asm.tree.LookupSwitchInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.MultiANewArrayInsnNode;
import org.objectweb.asm.tree.TableSwitchInsnNode;
import org.objectweb.asm.tree.TypeInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import java.util.*;
import java.util.stream.Collectors;
/***************************************************************************
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
@ -54,340 +36,361 @@ import the.bytecode.club.bytecodeviewer.BytecodeViewer;
/**
* @author Konloch
* @author Bibl
* @author GraxCode
*/
public class InstructionPrinter {
public class InstructionPrinter implements Opcodes {
/**
* The MethodNode to print
**/
private final MethodNode mNode;
private final TypeAndName[] args;
/**
* The MethodNode to print
**/
private final MethodNode mNode;
private final TypeAndName[] args;
protected int[] pattern;
protected boolean match;
protected int[] pattern;
protected boolean match;
protected List<AbstractInsnNode> matchedInsns;
protected Map<LabelNode, Integer> labels;
private boolean firstLabel = false;
private final List<String> info = new ArrayList<>();
protected List<AbstractInsnNode> matchedInsns;
protected Map<LabelNode, Integer> labels;
private boolean firstLabel = false;
private final List<String> info = new ArrayList<>();
public InstructionPrinter(MethodNode m, TypeAndName[] args) {
this.args = args;
mNode = m;
labels = new HashMap<>();
// matchedInsns = new ArrayList<AbstractInsnNode>(); // ingnored because
// match = false
match = false;
public InstructionPrinter(MethodNode m, TypeAndName[] args) {
this.args = args;
mNode = m;
labels = new HashMap<>();
precalculateLabelIndexes(m);
// matchedInsns = new ArrayList<AbstractInsnNode>(); // ingnored because
// match = false
match = false;
}
public InstructionPrinter(MethodNode m, InstructionPattern pattern, TypeAndName[] args) {
this(m, args);
InstructionSearcher searcher = new InstructionSearcher(m.instructions, pattern);
match = searcher.search();
if (match) {
for (AbstractInsnNode[] ains : searcher.getMatches()) {
Collections.addAll(matchedInsns, ains);
}
}
}
private void precalculateLabelIndexes(MethodNode m) {
int lIdx = 0;
for (AbstractInsnNode ain : m.instructions) {
if (ain.getType() == AbstractInsnNode.LABEL) {
labels.put((LabelNode) ain, lIdx++);
}
}
}
/**
* Creates the print
*
* @return The print as an ArrayList
*/
public List<String> createPrint() {
firstLabel = false;
info.clear();
for (AbstractInsnNode ain : mNode.instructions) {
String line = printInstruction(ain);
if (!line.isEmpty()) {
if (match) if (matchedInsns.contains(ain)) line = " -> " + line;
info.add(line);
}
}
if (firstLabel && BytecodeViewer.viewer.appendBracketsToLabels.isSelected()) info.add("}");
return info;
}
public String printInstruction(AbstractInsnNode ain) {
String line = "";
if (ain instanceof VarInsnNode) {
line = printVarInsnNode((VarInsnNode) ain);
} else if (ain instanceof IntInsnNode) {
line = printIntInsnNode((IntInsnNode) ain);
} else if (ain instanceof FieldInsnNode) {
line = printFieldInsnNode((FieldInsnNode) ain);
} else if (ain instanceof MethodInsnNode) {
line = printMethodInsnNode((MethodInsnNode) ain);
} else if (ain instanceof LdcInsnNode) {
line = printLdcInsnNode((LdcInsnNode) ain);
} else if (ain instanceof InsnNode) {
line = printInsnNode((InsnNode) ain);
} else if (ain instanceof JumpInsnNode) {
line = printJumpInsnNode((JumpInsnNode) ain);
} else if (ain instanceof LineNumberNode) {
line = printLineNumberNode((LineNumberNode) ain);
} else if (ain instanceof LabelNode) {
if (firstLabel && BytecodeViewer.viewer.appendBracketsToLabels.isSelected()) info.add("}");
LabelNode label = (LabelNode) ain;
if (mNode.tryCatchBlocks != null) {
List<TryCatchBlockNode> tcbs = mNode.tryCatchBlocks;
String starting = tcbs.stream().filter(tcb -> tcb.start == label).map(tcb -> "start TCB" + tcbs.indexOf(tcb)).collect(Collectors.joining(", "));
String ending = tcbs.stream().filter(tcb -> tcb.end == label).map(tcb -> "end TCB" + tcbs.indexOf(tcb)).collect(Collectors.joining(", "));
String handlers = tcbs.stream().filter(tcb -> tcb.handler == label).map(tcb -> "handler TCB" + tcbs.indexOf(tcb)).collect(Collectors.joining(", "));
if (!ending.isEmpty()) info.add("// " + ending);
if (!starting.isEmpty()) info.add("// " + starting);
if (!handlers.isEmpty()) info.add("// " + starting);
}
line = printLabelNode((LabelNode) ain);
if (BytecodeViewer.viewer.appendBracketsToLabels.isSelected()) {
if (!firstLabel) firstLabel = true;
line += " {";
}
} else if (ain instanceof TypeInsnNode) {
line = printTypeInsnNode((TypeInsnNode) ain);
} else if (ain instanceof FrameNode) {
line = printFrameNode((FrameNode) ain);
} else if (ain instanceof IincInsnNode) {
line = printIincInsnNode((IincInsnNode) ain);
} else if (ain instanceof TableSwitchInsnNode) {
line = printTableSwitchInsnNode((TableSwitchInsnNode) ain);
} else if (ain instanceof LookupSwitchInsnNode) {
line = printLookupSwitchInsnNode((LookupSwitchInsnNode) ain);
} else if (ain instanceof InvokeDynamicInsnNode) {
line = printInvokeDynamicInsNode((InvokeDynamicInsnNode) ain);
} else if (ain instanceof MultiANewArrayInsnNode) {
line = printMultiANewArrayInsNode((MultiANewArrayInsnNode) ain);
} else {
line += "UNADDED OPCODE: " + nameOpcode(ain.getOpcode()) + " " + ain;
}
public InstructionPrinter(MethodNode m, InstructionPattern pattern,
TypeAndName[] args) {
this.args = args;
mNode = m;
labels = new HashMap<>();
InstructionSearcher searcher = new InstructionSearcher(m.instructions, pattern);
match = searcher.search();
if (match) {
for (AbstractInsnNode[] ains : searcher.getMatches()) {
Collections.addAll(matchedInsns, ains);
}
return line;
}
protected String printVarInsnNode(VarInsnNode vin) {
StringBuilder sb = new StringBuilder();
sb.append(nameOpcode(vin.getOpcode()));
sb.append(" ");
sb.append(vin.var);
if (BytecodeViewer.viewer.debugHelpers.isSelected()) {
if (vin.var == 0 && !Modifier.isStatic(mNode.access)) {
sb.append(" // reference to self");
} else {
final int refIndex = vin.var - (Modifier.isStatic(mNode.access) ? 0 : 1);
if (refIndex >= 0 && refIndex < args.length - 1) {
sb.append(" // reference to ").append(args[refIndex].name);
}
}
}
/**
* Creates the print
*
* @return The print as an ArrayList
*/
public List<String> createPrint() {
firstLabel = false;
info.clear();
for (AbstractInsnNode ain : mNode.instructions) {
String line = printInstruction(ain);
if (!line.isEmpty()) {
if (match)
if (matchedInsns.contains(ain))
line = " -> " + line;
return sb.toString();
}
info.add(line);
}
}
if (firstLabel
&& BytecodeViewer.viewer.appendBracketsToLabels.isSelected())
info.add("}");
return info;
protected String printIntInsnNode(IntInsnNode iin) {
return nameOpcode(iin.getOpcode()) + " " + iin.operand;
}
protected String printFieldInsnNode(FieldInsnNode fin) {
String desc = Type.getType(fin.desc).getClassName();
if (desc.equals("null")) desc = fin.desc;
return nameOpcode(fin.getOpcode()) + " " + fin.owner + "." + fin.name + ":" + desc;
}
protected String printMethodInsnNode(MethodInsnNode min) {
StringBuilder sb = new StringBuilder();
sb.append(nameOpcode(min.getOpcode())).append(" ").append(min.owner).append(".").append(min.name);
String desc = min.desc;
try {
if (Type.getType(min.desc) != null) desc = Type.getType(min.desc).getClassName();
} catch (java.lang.AssertionError e) {
//e.printStackTrace();
} catch (java.lang.Exception e) {
e.printStackTrace();
}
public String printInstruction(AbstractInsnNode ain)
{
String line = "";
if (ain instanceof VarInsnNode) {
line = printVarInsnNode((VarInsnNode) ain);
} else if (ain instanceof IntInsnNode) {
line = printIntInsnNode((IntInsnNode) ain);
} else if (ain instanceof FieldInsnNode) {
line = printFieldInsnNode((FieldInsnNode) ain);
} else if (ain instanceof MethodInsnNode) {
line = printMethodInsnNode((MethodInsnNode) ain);
} else if (ain instanceof LdcInsnNode) {
line = printLdcInsnNode((LdcInsnNode) ain);
} else if (ain instanceof InsnNode) {
line = printInsnNode((InsnNode) ain);
} else if (ain instanceof JumpInsnNode) {
line = printJumpInsnNode((JumpInsnNode) ain);
} else if (ain instanceof LineNumberNode) {
line = printLineNumberNode((LineNumberNode) ain);
} else if (ain instanceof LabelNode) {
if (firstLabel
&& BytecodeViewer.viewer.appendBracketsToLabels
.isSelected())
info.add("}");
if (desc == null || desc.equals("null")) desc = min.desc;
line = printLabelnode((LabelNode) ain);
sb.append(desc);
if (BytecodeViewer.viewer.appendBracketsToLabels.isSelected()) {
if (!firstLabel)
firstLabel = true;
line += " {";
}
} else if (ain instanceof TypeInsnNode) {
line = printTypeInsnNode((TypeInsnNode) ain);
} else if (ain instanceof FrameNode) {
line = printFrameNode((FrameNode) ain);
} else if (ain instanceof IincInsnNode) {
line = printIincInsnNode((IincInsnNode) ain);
} else if (ain instanceof TableSwitchInsnNode) {
line = printTableSwitchInsnNode((TableSwitchInsnNode) ain);
} else if (ain instanceof LookupSwitchInsnNode) {
line = printLookupSwitchInsnNode((LookupSwitchInsnNode) ain);
} else if (ain instanceof InvokeDynamicInsnNode) {
line = printInvokeDynamicInsNode((InvokeDynamicInsnNode) ain);
} else if (ain instanceof MultiANewArrayInsnNode) {
line = printMultiANewArrayInsNode((MultiANewArrayInsnNode) ain);
} else {
line += "UNADDED OPCODE: " + nameOpcode(ain.getOpcode()) + " "
+ ain;
}
return sb.toString();
}
return line;
protected String printLdcInsnNode(LdcInsnNode ldc) {
if (ldc.cst instanceof String)
return nameOpcode(ldc.getOpcode()) + " \"" + StringEscapeUtils.escapeJava(ldc.cst.toString()) + "\" (" + ldc.cst.getClass().getCanonicalName() + ")";
return nameOpcode(ldc.getOpcode()) + " " + StringEscapeUtils.escapeJava(ldc.cst.toString()) + " (" + ldc.cst.getClass().getCanonicalName() + ")";
}
protected String printInsnNode(InsnNode in) {
return nameOpcode(in.getOpcode());
}
protected String printJumpInsnNode(JumpInsnNode jin) {
return nameOpcode(jin.getOpcode()) + " L" + resolveLabel(jin.label);
}
protected String printLineNumberNode(LineNumberNode lnn) {
return "// line " + lnn.line;
}
protected String printLabelNode(LabelNode label) {
return "L" + resolveLabel(label);
}
protected String printTypeInsnNode(TypeInsnNode tin) {
try {
String desc = tin.desc;
try {
if (Type.getType(tin.desc) != null) desc = Type.getType(tin.desc).getClassName();
if (desc.equals("null")) desc = tin.desc;
} catch (java.lang.ArrayIndexOutOfBoundsException ignored) {
}
return nameOpcode(tin.getOpcode()) + " " + desc;
} catch (Exception e) {
return nameOpcode(tin.getOpcode()) + " " + tin.desc;
}
}
protected String printIincInsnNode(IincInsnNode iin) {
return nameOpcode(iin.getOpcode()) + " " + iin.var + " " + iin.incr;
}
protected String printTableSwitchInsnNode(TableSwitchInsnNode tin) {
StringBuilder line = new StringBuilder(nameOpcode(tin.getOpcode()) + " \n");
List<?> labels = tin.labels;
int count = 0;
for (int i = tin.min; i < tin.max + 1; i++) {
line.append(" val: ").append(i).append(" -> ").append("L").append(resolveLabel((LabelNode) labels.get(count++))).append("\n");
}
line.append(" default" + " -> L").append(resolveLabel(tin.dflt));
return line.toString();
}
protected String printLookupSwitchInsnNode(LookupSwitchInsnNode lin) {
StringBuilder line = new StringBuilder(nameOpcode(lin.getOpcode()) + ": \n");
List<?> keys = lin.keys;
List<?> labels = lin.labels;
for (int i = 0; i < keys.size(); i++) {
int key = (Integer) keys.get(i);
LabelNode label = (LabelNode) labels.get(i);
line.append(" val: ").append(key).append(" -> ").append("L").append(resolveLabel(label)).append("\n");
}
protected String printVarInsnNode(VarInsnNode vin) {
StringBuilder sb = new StringBuilder();
sb.append(nameOpcode(vin.getOpcode()));
sb.append(vin.var);
if (BytecodeViewer.viewer.debugHelpers.isSelected()) {
if (vin.var == 0 && !Modifier.isStatic(mNode.access)) {
sb.append(" // reference to self");
} else {
final int refIndex = vin.var
- (Modifier.isStatic(mNode.access) ? 0 : 1);
if (refIndex >= 0 && refIndex < args.length - 1) {
sb.append(" // reference to ").append(args[refIndex].name);
}
}
}
line.append(" default" + " -> L").append(resolveLabel(lin.dflt));
return line.toString();
}
return sb.toString();
protected String printInvokeDynamicInsNode(InvokeDynamicInsnNode idin) {
StringBuilder sb = new StringBuilder();
sb.append(nameOpcode(idin.getOpcode())).append(" ").append(idin.bsm.getOwner()).append('.').append(idin.bsm.getName()).append(idin.bsm.getDesc()).append(" : ").append(idin.name).append(idin.desc);
if (idin.bsmArgs != null) {
for (Object o : idin.bsmArgs) {
sb.append(" ");
sb.append(o.toString());
}
}
protected String printIntInsnNode(IntInsnNode iin) {
return nameOpcode(iin.getOpcode()) + " " + iin.operand;
return sb.toString();
}
protected String printMultiANewArrayInsNode(MultiANewArrayInsnNode mana) {
return nameOpcode(mana.getOpcode()) + " " + mana.dims + " : " + mana.desc;
}
private String printFrameNode(FrameNode frame) {
StringBuilder sb = new StringBuilder();
sb.append(nameFrameType(frame.type)).append(" ");
sb.append("(Locals");
if (frame.local != null && !frame.local.isEmpty()) {
sb.append("[").append(frame.local.size()).append("]: ");
sb.append(frame.local.stream().map(this::printFrameObject).collect(Collectors.joining(", ")));
} else {
sb.append("[0]");
}
sb.append(") ");
protected String printFieldInsnNode(FieldInsnNode fin) {
String desc = Type.getType(fin.desc).getClassName();
if (desc.equals("null"))
desc = fin.desc;
return nameOpcode(fin.getOpcode()) + " " + fin.owner + "." + fin.name
+ ":" + desc;
sb.append("(Stack");
if (frame.stack != null && !frame.stack.isEmpty()) {
sb.append("[").append(frame.stack.size()).append("]: ");
sb.append(frame.stack.stream().map(this::printFrameObject).collect(Collectors.joining(", ")));
} else {
sb.append("[0]");
}
sb.append(") ");
protected String printMethodInsnNode(MethodInsnNode min) {
StringBuilder sb = new StringBuilder();
sb.append(nameOpcode(min.getOpcode())).append(" ").append(min.owner).append(".").append(min.name);
return sb.toString();
}
String desc = min.desc;
try {
if (Type.getType(min.desc) != null)
desc = Type.getType(min.desc).getClassName();
} catch (java.lang.AssertionError e) {
//e.printStackTrace();
} catch (java.lang.Exception e) {
e.printStackTrace();
}
if (desc == null || desc.equals("null"))
desc = min.desc;
sb.append(desc);
return sb.toString();
private String printFrameObject(Object obj) {
if (obj instanceof LabelNode) return "label [L" + resolveLabel((LabelNode) obj) + "]";
if (obj instanceof Integer) {
switch ((int) obj) {
case 0:
return "top";
case 1:
return "int";
case 2:
return "float";
case 3:
return "double";
case 4:
return "long";
case 5:
return "null";
case 6:
return "uninitialized this";
default:
return "unknown";
}
}
if (obj instanceof String) return "reference [" + obj + "]";
return "unknown [" + obj.toString() + "]";
}
protected String printLdcInsnNode(LdcInsnNode ldc) {
if (ldc.cst instanceof String)
return nameOpcode(ldc.getOpcode()) + " \""
+ StringEscapeUtils.escapeJava(ldc.cst.toString()) + "\" ("
+ ldc.cst.getClass().getCanonicalName() + ")";
return nameOpcode(ldc.getOpcode()) + " "
+ StringEscapeUtils.escapeJava(ldc.cst.toString()) + " ("
+ ldc.cst.getClass().getCanonicalName() + ")";
private String nameFrameType(int type) {
switch (type) {
case F_NEW:
return " f_new";
case F_FULL:
return " f_full";
case F_APPEND:
return " f_append";
case F_CHOP:
return " f_chop";
case F_SAME:
return " f_same";
case F_SAME1:
return " f_same1";
default:
return " f_unknown" + type;
}
}
protected String printInsnNode(InsnNode in) {
return nameOpcode(in.getOpcode());
}
protected String nameOpcode(int opcode) {
return " " + OpcodeInfo.OPCODES.get(opcode).toLowerCase();
}
protected String printJumpInsnNode(JumpInsnNode jin) {
return nameOpcode(jin.getOpcode()) + " L"
+ resolveLabel(jin.label);
}
protected String printLineNumberNode(LineNumberNode lnn) {
return "// line " + lnn.line;
}
protected String printLabelnode(LabelNode label) {
return "L" + resolveLabel(label);
}
protected String printTypeInsnNode(TypeInsnNode tin) {
try {
String desc = tin.desc;
try {
if (Type.getType(tin.desc) != null)
desc = Type.getType(tin.desc).getClassName();
if (desc.equals("null"))
desc = tin.desc;
} catch (java.lang.ArrayIndexOutOfBoundsException ignored) {
}
return nameOpcode(tin.getOpcode()) + " " + desc;
} catch (Exception e) {
return nameOpcode(tin.getOpcode()) + " " + tin.desc;
}
}
protected String printIincInsnNode(IincInsnNode iin) {
return nameOpcode(iin.getOpcode()) + " " + iin.var + " " + iin.incr;
}
protected String printTableSwitchInsnNode(TableSwitchInsnNode tin) {
StringBuilder line = new StringBuilder(nameOpcode(tin.getOpcode()) + " \n");
List<?> labels = tin.labels;
int count = 0;
for (int i = tin.min; i < tin.max + 1; i++) {
line.append(" val: ").append(i).append(" -> ").append("L")
.append(resolveLabel((LabelNode) labels.get(count++))).append("\n");
}
line.append(" default" + " -> L").append(resolveLabel(tin.dflt));
return line.toString();
}
protected String printLookupSwitchInsnNode(LookupSwitchInsnNode lin) {
StringBuilder line = new StringBuilder(nameOpcode(lin.getOpcode()) + ": \n");
List<?> keys = lin.keys;
List<?> labels = lin.labels;
for (int i = 0; i < keys.size(); i++) {
int key = (Integer) keys.get(i);
LabelNode label = (LabelNode) labels.get(i);
line.append(" val: ").append(key).append(" -> ").append("L")
.append(resolveLabel(label)).append("\n");
}
line.append(" default" + " -> L").append(resolveLabel(lin.dflt));
return line.toString();
}
protected String printInvokeDynamicInsNode(InvokeDynamicInsnNode idin) {
StringBuilder sb = new StringBuilder();
sb.append(nameOpcode(idin.getOpcode())).append(" ").append(idin.bsm.getOwner()).append('.')
.append(idin.bsm.getName()).append(idin.bsm.getDesc()).append(" : ")
.append(idin.name).append(idin.desc);
if (idin.bsmArgs != null) {
for (Object o : idin.bsmArgs) {
sb.append(" ");
sb.append(o.toString());
}
}
return sb.toString();
}
protected String printMultiANewArrayInsNode(MultiANewArrayInsnNode mana) {
return nameOpcode(mana.getOpcode()) + " " + mana.dims + " : " + mana.desc;
}
private String printFrameNode(FrameNode frame) {
StringBuilder sb = new StringBuilder();
sb.append(nameOpcode(frame.getOpcode())).append(" ");
sb.append("(Locals");
if (frame.local != null
&& frame.local.size() > 0) {
sb.append("[").append(frame.local.size()).append("]:");
sb.append(" ");
sb.append(frame.local.get(0).toString());
if (frame.local.size() > 1) {
for (int i = 1; i < frame.local.size(); i++) {
sb.append(", ");
sb.append(frame.local.get(i).toString());
}
}
} else {
sb.append("[0]: null");
}
sb.append(") ");
sb.append("(Stack");
if (frame.stack != null
&& frame.stack.size() > 0) {
sb.append("[").append(frame.stack.size()).append("]:");
sb.append(" ");
sb.append(frame.stack.get(0).toString());
if (frame.stack.size() > 1) {
for (int i = 1; i < frame.stack.size(); i++) {
sb.append(", ");
sb.append(frame.stack.get(i).toString());
}
}
} else {
sb.append("[0]: null");
}
sb.append(")");
return sb.toString();
}
protected String nameOpcode(int opcode) {
return " " + OpcodeInfo.OPCODES.get(opcode).toLowerCase();
}
protected int resolveLabel(LabelNode label) {
if (labels.containsKey(label)) {
return labels.get(label);
} else {
int newLabelIndex = labels.size() + 1;
protected int resolveLabel(LabelNode label) {
if (labels.containsKey(label)) {
return labels.get(label);
} else {
/*int newLabelIndex = labels.size() + 1;
labels.put(label, newLabelIndex);
return newLabelIndex;
}
return newLabelIndex;*/
throw new IllegalStateException("LabelNode index not found. (Label not in InsnList?)");
}
}
public static void saveTo(File file, InstructionPrinter printer) {
try (FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw)) {
for (String s : printer.createPrint()) {
bw.write(s);
bw.newLine();
}
} catch (IOException e) {
BytecodeViewer.handleException(e);
}
public static void saveTo(File file, InstructionPrinter printer) {
try (FileWriter fw = new FileWriter(file); BufferedWriter bw = new BufferedWriter(fw)) {
for (String s : printer.createPrint()) {
bw.write(s);
bw.newLine();
}
} catch (IOException e) {
BytecodeViewer.handleException(e);
}
}
}

View file

@ -57,6 +57,9 @@ public class MethodNodeDecompiler {
if (m.name.equals("<init>")) {
sb.append(class_);
} else if (!m.name.equals("<clinit>")) {
Type returnType = Type.getReturnType(m.desc);
sb.append(returnType.getClassName());
sb.append(" ");
sb.append(m.name);
}