Tuesday, 12 May 2009

Netifera uses JamVM as remote probe

Netifera is a very interesting 100% Java-based Open Source network security platform. The next version will include a probe, which is a "deployable software agent that makes it possible to run all netifera platform tools remotely".

The probe uses JamVM and a cut-down version of GNU Classpath. This is downloaded onto the remote site to run the netifera tools. My thanks to Claudio Castiglia (of Netifera) for sending me the following link to a webcast showing the probe in action:

http://netifera.com/video/netifera_java_virtual_machine_as_shellcode


JamVM and GNU Classpath are mentioned starting 14:54 into the webcast in the discussion of the probe architecture.

Monday, 11 May 2009

JamVM on Beagle Board

I've been intending to get a Beagle Board for quite a while now, to replace a Neo1973 as the development platform for JamVM on ARM. The Neo has an ARM920T core, and I've been particularly wanting to test JamVMs code-copying JIT on a more modern implementation (the Beagle Board has a Cortex A8). But I've been waiting for the Rev C board, as this has working EHCI USB host, and 256MB RAM (previous revisions had 128MB). The board arrived 2 weeks ago, but I haven't had much time to set it up until now...

So far, the results are quite encouraging. SciMark 2.0 shows a 55% speed improvement:



While jBYTEmark shows an 82% improvement on Integer tests:



The option -Xcodestats prints out the size of the JIT code-cache when the VM exits. This shows 77K was used after running SciMark 2.0, and 178K after jBYTEmark. This is using the code-profiling introduced in JamVM 1.5.2.

Tuesday, 17 March 2009

JRuby 1.2.0RC2

I read with interest Jeroen's recent post on his blog about his experiences running JRuby 1.2.0RC2 on IKVM. I know I don't run enough "real-world" tests on JamVM, so I finally got around to trying to run it on JamVM over the weekend. Then wished I hadn't. I secretly hoped it would "just work", but it almost immediately segv-ed. This was the first of 5 problems.

The segv was relatively easy to find and fix. A regression introduced in JamVM 1.5.1, when I added unloader objects to unload JNI libraries after the classloader which loaded them is garbage-collected. This was itself a fix for library unloading, which used to be done within GC, but broke if the JNI_OnUnload function called back into Java.

Basically, I didn't take into account libraries which have a JNI_OnUnload function being loaded by the boot classloader (the NULL loader). This is pointless, as the boot classloader is never collected, and therefore no library loaded by it can be unloaded. However, the fix was simple - just ignore them.

The next problem was with MemoryManagerMXBean. I spent some time implementing native support for ThreadMXBean in JamVM 1.4.4 as part of the thread re-work, but never got round to implementing the full set, as nothing much seemed to use them. For now, a simple implementation which just returns "no memory managers" appears to be sufficient.

After that there was a problem with annotations, where an AnnotationTypeMismatchException was being thrown. This took some time to track down because I had to remember how annotations worked! It ended up being a mismatch between an annotation array value and the method return type. When parsing the annotation, the array values can be any one of a number of types, so in JamVM an Object array is created (when the array is created, the elements haven't yet been parsed so the type isn't known). But the method return value is the specific type, in this case String[]. Luckily, a similar problem has been found with the implementation in gcj, so I was able to adapt the fix into JamVMs version of sun.reflect.annotation.AnnotationInvocationHandler.

Problem number 4 was with VMClassLoader.getPackage(). The default GNU Classpath implementation relies on a META-INF/INDEX.LIST file existing in the first Jar in the bootclasspath. JRuby uses Constantine, which uses the package name to load an appropriate constant class. As the Constantine Jar is added to the bootclasspath, even if the INDEX.LIST existed, it wouldn't have any package information for it. A quick and dirty implementation of VMClassLoader.getBootPackages() which doesn't need INDEX.LIST fixed this.

Finally, there was a problem with Class.getSimpleName(). The simple name is appended to the package name to locate the constant class. However, the GNU Classpath implementation of getSimpleName (which delegates to VMClass) is broken. Again, I took the fix from gcj.

After all this, jRuby runs!
rob@dougal:~$ jruby hello.rb
Hello World!

The next thing to try was jirb (interactive shell). For some reason, the default prompt doesn't work (nothing is shown, it may be related to sun.misc.Signal, as jirb complains about an unsupported trap). However, the simple prompt does.
rob@dougal:~$ jirb --prompt simple
trap not supported or not allowed by this VM
>> include_class java.lang.System
include_class java.lang.System
=> Java::JavaLang::System
>> System.getProperty("java.vm.name")
System.getProperty("java.vm.name")
=> "JamVM"
>> System.getProperty("java.vendor")
System.getProperty("java.vendor")
=> "GNU Classpath"
>> quit
quit

Monday, 2 March 2009

Benchmarks

A couple of people after my talk at FOSDEM asked me where the benchmarks were. I didn't have any partly because I didn't think there was time in the talk, partly because I didn't know what to benchmark against, and mostly because I hadn't had time to do any.

So, I've finally done some. I've benchmarked against the JDK template interpreter, because of the interest due to the recent work of Shark and Zero. The benchmarks are from SPECjvm2008. Not all of these run with GNU Classpath, and from the rest, I've selected benchmarks which should hopefully not be influenced by the different class libraries.
Note, these benchmarks are not compliant, and I am in no way publishing these results. For the record, the benchmarks were ran on an Athlon 64x2 3800+.