This document discusses advanced Java debugging using bytecode. It explains that bytecode is the low-level representation of Java programs that is executed by the Java Virtual Machine (JVM). It shows examples of decompiling Java source code to bytecode instructions and evaluating bytecode on a stack. Various bytecode visualization and debugging tools are demonstrated. Key topics like object-oriented aspects of bytecode and the ".class" file format are also covered at a high-level.
27. 1 2 3 / - 4 5 % 6 * +
Let us give
names to these
operations
push 1
push 2
push 3
div
sub
push 4
push 5
mod
push 6
mul
add
28. int a = 1, b = 2, c = 3, d = 4, e = 5, f = 6;
int r = (a - (b / c)) + ((d % e) * f);
This is what a Java
compiler generates
iload_1
iload_2
iload_3
idiv
isub
iload 4
iload 5
irem
iload 6
imul
iadd
istore 7
push 1
push 2
push 3
div
sub
push 4
push 5
mod
push 6
mul
add
ourbytecode
Javabytecodes
38. public static void
main(java.lang.String[]);
descriptor: ??
flags: ??, ??
Code:
stack=??, locals=??, args_size=??
Pop
Quiz
public static void main(String []args) {
int a = 1, b = 2, c = 3, d = 4, e = 5, f = 6;
int r = (a - (b / c)) + ((d % e) * f);
System.out.println("" + r);
}
48. class URL {
public static void main(String []args) {
http://www.google.com
System.out.println("Hello");
}
}
http: is a label and // is start
of a comment!!
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String Hello
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
49. Question
What will be the output of this program?
class Color {
int red, green, blue;
void Color() {
red = 10; green = 10; blue = 10;
}
void printColor() {
System.out.println("red: " + red + " green: " + green + " blue: " + blue);
}
public static void main(String [] args) {
Color color= new Color();
color.printColor();
}
}
A. Compiler error: no constructor provided for the class
B. Compiles fine, and when run, it prints the following: red: 0 green: 0 blue: 0
C. Compiles fine, and when run, it prints the following: red: 10 green: 10 blue: 10
D. Compiles fine, and when run, crashes by throwing NullPointerException
50. Answer
What will be the output of this program?
class Color {
int red, green, blue;
void Color() {
red = 10; green = 10; blue = 10;
}
void printColor() {
System.out.println("red: " + red + " green: " + green + " blue: " + blue);
}
public static void main(String [] args) {
Color color= new Color();
color.printColor();
}
}
A. Compiler error: no constructor provided for the class
B. Compiles fine, and when run, it prints the following: red: 0 green: 0 blue: 0
C. Compiles fine, and when run, it prints the following: red: 10 green: 10 blue: 10
D. Compiles fine, and when run, crashes by throwing NullPointerException
51. $ javap Color.class
Compiled from "Color.java"
class Color {
int red;
int green;
int blue;
Color();
void Color();
void printColor();
public static void main(java.lang.String[]);
}
Color();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
void Color();
Code:
0: aload_0
1: bipush 10
3: putfield #2 // Field red:I
6: aload_0
7: bipush 10
9: putfield #3 // Field green:I
12: aload_0
13: bipush 10
15: putfield #4 // Field blue:I
18: return
Aha! The generated code
doesn’t look right!
void Color() {
red = 10; green = 10; blue = 10;
}
52. abstract class Printer {
private Integer portNumber = getPortNumber();
abstract Integer getPortNumber();
public static void main(String[]s) {
Printer p = new LPDPrinter();
System.out.println(p.portNumber);
}
}
class LPDPrinter extends Printer {
/* Line Printer Deamon port no is 515 */
private Integer defaultPortNumber = 515;
Integer getPortNumber() {
return defaultPortNumber;
}
}
53. abstract class Printer {
private Integer portNumber = getPortNumber();
abstract Integer getPortNumber();
public static void main(String[]s) {
Printer p = new LPDPrinter();
System.out.println(p.portNumber);
}
}
class LPDPrinter extends Printer {
/* Line Printer Deamon port no is 515 */
private Integer defaultPortNumber = 515;
Integer getPortNumber() {
return defaultPortNumber;
}
}
$ javap -c LPDPrinter.class
Compiled from "Printer.java"
class LPDPrinter extends Printer {
LPDPrinter();
Code:
0: aload_0
1: invokespecial #1 // Method Printer."<init>":()V
4: aload_0
5: sipush 515
8: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/
lang/Integer;
11: putfield #3 // Field defaultPortNumber:Ljava/lang/Integer;
14: return
java.lang.Integer getPortNumber();
Code:
0: aload_0
1: getfield #3 // Field defaultPortNumber:Ljava/lang/Integer;
4: areturn
}
Initialisation happens *after*
the base class constructor got
54. javap can get you lost in
details!
int ch = 0;
while((ch = inputFile.read()) != 0) {
System.out.print(ch);
}
48: iconst_0
49: istore 7
51: aload 5
53: invokevirtual #8 // Method java/io/FileReader.read:()I
56: dup
57: istore 7
59: ifeq 73
62: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream
65: iload 7
67: invokevirtual #10 // Method java/io/PrintStream.print:(I)V
55. • Difficult to debug when reflection and runtime class
generation is involved
• Obfuscated bytecodes are extremely difficult to debug
56. FUN PROJECT
The best way to learn Java bytecodes is to implement a Java
disassembler on your own!
For implementation, read the documentation of Java
bytecodes (in the JVM specification) and use javap tool as
the reference implementation.