When i said ALL the native stuff was working on iOS i was of course wrong. Turns out the IKVM MonoTouch port was missing some essential capabilities, namely, calling into Java from native code. This is needed for Box2D callbacks and things like determining the position of a direct ByteBuffer in the OpenGL wrapper code, among other things.
When Michael started porting IKVM to MonoTouch he ran into a couple of issues, among which one was the way IKVM handles reflection (which in turn is also used when calling Java from native code). IKVM actually performs code generation to speed up reflection, much like Java tools like ASM allow one to do. On iOS this is a no-go, since you can’t make memory executable and hence can’t JIT compile things. Michael went ahead and kinda operated on an open heart, ripping out the code generation reflection backend and replacing it with the slower, standard reflection that just looks things up like crazy all the time.
This works pretty well, safe for some performance loss. Except that a crucial part was missing: the JNI methods native code can call to invoke a method on a Java object went nowhere. It took me a while to figure this out, as i had to navigate the code of IKVM manually. Eventually i found the culprit: MemberWrapper#invokeJni was not implemented for the MonoTouch port. I changed it to use the slow reflection mechanism and things started working as expected. I issued a pull request for the simple fix which you can find here.
Moral of the story: our dependency on native code can turn up surprising issues on iOS at times.