-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathByteCodePrinter.java
More file actions
90 lines (82 loc) · 3.53 KB
/
Copy pathByteCodePrinter.java
File metadata and controls
90 lines (82 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package org.example.misc;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TryCatchBlockNode;
import org.objectweb.asm.tree.analysis.*;
import org.objectweb.asm.util.Textifier;
import org.objectweb.asm.util.TraceMethodVisitor;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
public class ByteCodePrinter {
private static String getUnqualifiedName(final String name) {
var lastSlashIndex = name.lastIndexOf('/');
if (lastSlashIndex == -1) {
return name;
} else {
int endIndex = name.length();
if (name.charAt(endIndex - 1) == ';') {
endIndex--;
}
int lastBracketIndex = name.lastIndexOf('[');
if (lastBracketIndex == -1) {
return name.substring(lastSlashIndex + 1, endIndex);
}
return name.substring(0, lastBracketIndex + 1) + name.substring(lastSlashIndex + 1, endIndex);
}
}
private static void analyzeMethod(
final MethodNode method, final Analyzer<BasicValue> analyzer, final PrintWriter printWriter) {
var textifier = new Textifier();
var 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);
var stringBuilder = new StringBuilder();
var 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 void printBytecode(ClassNode cn) {
var sortMethod = cn.methods.get(1);
var analyzer = new CheckFrameAnalyzer<>(new BasicVerifier());
try {
analyzer.analyze("dummy", sortMethod);
} catch (AnalyzerException e) {
throw new RuntimeException(e);
}
var pw = new PrintWriter(System.out);
analyzeMethod(sortMethod, analyzer, pw);
pw.flush();
}
public void printBubbleSortBytecode() throws IOException {
var cn = new ClassNode();
var classFileBytes = Files.readAllBytes(Path.of("build/classes/java/main/org/itmo/lab1/example/BubbleSort.class"));
var classReader = new ClassReader(classFileBytes);
classReader.accept(cn, ClassReader.EXPAND_FRAMES);
printBytecode(cn);
}
}