Tuesday, April 12, 2005

Of virtual machines

Of late ive been interested in virtual machine stuff. Naturally (for me), the first vm to explore was jvm.

JVM is a stack based vm. It means whenever u want to execute an operation, the operands are popped from stack and executed. For eg a simple addition for 11 + 12, you have to do these
(im using Joshua Engel's Oolong assembler and Gnoloo disassembler)

bipush 12
bipush 13

ie push 12 and 13 to stack and execute iadd. iadd will pop two operands from stack (the 12 and 13), compute the result and push it back to stack. So finally stack will end up having a value of 25.

There are other kinds of vm's like the register based ones. Parrot is an example. In these kind of vm's there is no need to spend time on pushing and popping operands, instead operands can be loaded/stored in registers.

Ok going back to jvm .. each method will have its own operand stack, its local variables. Local variables are place where you can store variables. It is numbered starting from 0 (upto 65536 i guess).
Usually in a non static method, "this" reference will be stored in location 0, then all the method parameters are stored starting from 1 etc

so for eg if there is a method

void test(int i, float j)

it means
this --> 0 //stored in local variable 0
i --> 1 //stored in local variable 1
j -->2 //stored in local variable 2

so i can be accessed by using "iload 1" instruction and j by using "fload 2".

This is different from C where parameters are pushed onto stack i believe.

There are some interesting things supported by jvm. One example is support of methods with same signatures, but different return types.

In java language, you cant have both these methods coexisting in same class

public Integer test() {..}
public String test() {..}

because method signature consists of method name and its parameteres and does not contain return types.
This makes sense as you will never specify the return type while invoking

i = test();

But the jvm perfectly supports the above two methods in same class. The thing there is whenever you invoke any method, you need to specify the return types as well.

so to invoke the first version, you would be saying

invokevirtual TestClass/test() Ljava/lang/Integer;

and to invoke the second

invokevirtual TestClass/test() Ljava/lang/String;

Here is a code which does exactly this

.class T14
.method static test() Ljava/lang/String;
ldc "this is test"
.end method

.method static test() Ljava/lang/Integer;
new java/lang/Integer
invokespecial java/lang/Integer/(I) V
.end method

.method public static main([Ljava/lang/String;) V
getstatic java/lang/System/out Ljava/io/PrintStream;

invokestatic T14/test() Ljava/lang/String;
invokevirtual java/io/PrintStream/println(Ljava/lang/Object;) V

invokestatic T14/test() Ljava/lang/Integer;
invokevirtual java/io/PrintStream/println(Ljava/lang/Object;) V
.end method
.end class

when you run this it prints both
C:\shibin\src\jsm\inher>java COM.sootNsmoke.oolong.Oolong T14.j

C:\shibin\src\jsm\inher>java T14
this is test

More things later

No comments: