Today we are going to look at a real example of bytecode, a "Hello, world" program.
public class Example {
int number = 4;
public Example() {
System.out.println("Hello, world!");
System.out.println("Number: " + number);
}
public static void main(String[] args) {
new Example();
}
}
All this really does is initialize the Example class, printing Hello, world! and Number: 4.
Now, what happens when we disassemble this (after compiling this of course)?
$ javap -c Example
Compiled from "Example.java"
public class Example extends java.lang.Object{
int number;
public Example();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: aload_0
5: iconst_4
6: putfield #2; //Field number:I
9: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
12: ldc #4; //String Hello, world!
14: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
17: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
20: new #6; //class java/lang/StringBuilder
23: dup
24: invokespecial #7; //Method java/lang/StringBuilder."":()V
27: ldc #8; //String Number:
29: invokevirtual #9; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
32: aload_0
33: getfield #2; //Field number:I
36: invokevirtual #10; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
39: invokevirtual #11; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
42: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
45: return
public static void main(java.lang.String[]);
Code:
0: new #12; //class Example
3: dup
4: invokespecial #13; //Method "":()V
7: pop
8: return
}
At this point, you will start to see classes, methods, line numbers (these don't relate directly to the source code), and of course, bytecodes. On the right of some of these bytecodes, the numbers relate to the values in the constant pool.
The constant pool stores many things, such as numbers, class names, signatures, string, all kinds of things.
Now, lets explore the very first line of the program, in the main method:
public static void main(java.lang.String[]);
Code:
0: new #12; //class Example
3: dup
4: invokespecial #13; //Method "":()V
7: pop
8: return
Line 0 creates a new object determined by the two bytes following the instruction (that's why the next instruction is on line 3 -- 0, 1 and 2 are taking up space), which correspond to the constant pool. In this case, the bytes are referring to the twelfth constant in the constant pool, a class by the name of Example (sounds familiar, right).
Line 3 simply duplicates the new instance of this class, therefore there are now two of the same objects on the top of the stack. This is done so we can refer to the object later on, as opposed to losing it right as we call the
Line 4 uses the object on the top of the stack and two other bytes (once again, referring to the constant pool), referring to the method
Line 7 pops the top-most part of the stack off. This means that anything that was returned is now gone, but that's good, there was nothing we needed to return!
Line 8, you guessed it, returns from the method. That's it.
Next post we are going to look at the Example constructor in the same manner.
See you soon!
This is cool, looking forward to learning more. How do I follow your blog? I don't see a follow ap anywhere.
ReplyDeleteOf course I forgot that.
ReplyDeleteI'll try and put that bar back on the top, but in the meantime, you can go here:
http://www.blogger.com/follow-blog.g?blogID=7902421180310521150
Thanks for the info!
ReplyDeleteNice blog, I can't really understand quite well programming language but I'm trying. Following!
ReplyDeleteOk, the link worked, thanks!
ReplyDeleteSweet blog following!!!
ReplyDeleteDone working on the design. I like it much more now! :D
ReplyDelete