Just the JVM m’aam

Previously I was looking at Java versus Python performance (here) and I was quite surprised (well not surprised, but more intruiged) by the JVM startup speed so I thought i’d have a bit more of a look to satisfy my curiosity. I don’t have all the answers so don’t hassle me, but what I started doing was using the JNI to create a JVM from a simple C command as opposed to using the java command to do the work and invoke the classloader etc. Anyway, this is how you do it in case you’re suitably bored and want to have a go 🙂

Here is the ‘c’ code which is a slightly modified version from the JNI reference manual:


#include <jni.h>
#include <stdlib.h>

#define USER_CLASSPATH “.” /* where to find Prog.class */

int main() {

JNIEnv *env;
JavaVM *jvm;
jint res;
jclass cls;
jmethodID mid;
jclass stringClass;
jobjectArray args;

JavaVMInitArgs vm_args;
JavaVMOption options[1];
options[0].optionString =
“-Djava.class.path=” USER_CLASSPATH;
vm_args.version = JNI_VERSION_1_6;
vm_args.options = options;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = JNI_TRUE;
/* Create the Java VM */
res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

if (res < 0) {
fprintf(stderr, “Can’t create Java VM\n”);
exit(1);
}
exit(0); /* here */
cls = (*env)->FindClass(env, “Prog”);
if (cls == NULL) {
goto destroy;
}

mid = (*env)->GetStaticMethodID(env, cls, “main”,
“([Ljava/lang/String;)V”);
if (mid == NULL) {
goto destroy;
}
args = NULL;
(*env)->CallStaticVoidMethod(env, cls, mid, args);

destroy:
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
}
(*jvm)->DestroyJavaVM(jvm);
}
Additionally here is the Java code for the class executed by the JVM when instantiated.

public class Prog {
public static void main(String[] args) {
System.out.println("Hello World");
}
}

We wont talk about how wordpress has formatted the above – oh well you get the idea 😉

Get things compiled and linked

javac Prog.java
gcc -I /usr/local/jdk1.7.0/include/ -I /usr/local/jdk1.7.0/include/linux/ -L /usr/local/jdk1.7.0/jre/lib/i386 -L /usr/local/jdk1.7.0/jre/lib/i386/client -ljava -ljvm -lverify -o invoke invoke.c

noting that i’m using an openjdk code drop

export LD_LIBRARY_PATH=/usr/local/jdk1.7.0/jre/lib/i386:/usr/local/jdk1.7.0/jre/lib/i386/client

and you should be able to ./invoke to check it out. If you review the invoke.c code above you’ll see an exit(0) statement with comment ‘here’. If you leave that in and time the execution you will see that the JVM instantiation isn’t that bad which is more in line with the empty python example mentioned in the previous blog entry. Removing the exit should see the JVM instantiated and the class file executed.

Interestingly just such a test reveals a far better comparion for VM instantiation with nothing to execute than the previous test. In this case the ratio now becomes :

Test Ratio (Java/Python)
Interpreter Init 1.6
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s