JamVM port to iPhone?

J.L. Allen
1 2 > >> (Page 1 of 2)
  • J.L. Allen
    J.L. Allen

    What does porting JamVM require (in terms of effort)?  Specifically, porting it to the iPhone, which uses an ARM CPU and runs Mac OS X.  I don't really understand how the whole CPU/OS interplay here, but would it be possible to mix-and-match stuff from arm-linux and powerpc-darwin to achieve this?  Apparently, the CPU is optimized for Java, but unfortunately Apple has turned against Java.

    • dljava

      Hello Mauvila,

      I've been attempting porting Kaffe to the iPhone for some time but I'm willing to look at JamVM (as well as a couple other VMs). Let me know (off list) if you can help out. Basically you need to cross compile both GNU classpath and the JamVM, and yes you need to merge some of the config files for arm and darwin (that's what I did with Kaffe) to get it to compile. Once compiled (trial and error with configure params as well) you may run into run time issues (as I have -  still not there yet).


    • Robert Lougher
      Robert Lougher


      Yes, I expect it will be relatively easy to get JamVM working on the iPhone (at least for console  apps).  The biggest effort will be in getting an iPhone toolchain, and getting the built packages onto the iPhone.  However, as you're investigating a port I expect you probably already have these (Googling shows a toolchain is available, as part of the "jailbreak" efforts).

      There are two calling conventions in use for ARM.  The new ARM EABI standard, which recent ARM Linux distributions use or the older OABI.  Both of these are supported by JamVM.  Assuming Apple's used one of these, you should simply be able to copy the linux/arm directory to darwin.  However, you will also need to update the darwin/Makefile.am file, and the top-level configure.ac to recognise the platform.  This is trivial.

      BTW, I have cross-compiled, and have had JamVM working happily on OpenMoko (the EABI work was done using a Neo1973).  I'm also interested in getting JamVM working on the iPhone (the iPhone was released in the UK on Friday, I got one on Saturday).  Unfortunately it's using firmware 1.1.2 which hasn't been hacked yet.


    • dljava

      Yes I've got the toolchain working sucessfully, just need some pointers on cross compiling jamvm as adding arm to darwin/Makefile.am wasn't enough, I need somehow to specify "unknown" or "apple" somewhere:


      configure: error: arm-unknown-darwin not supported


    • J.L. Allen
      J.L. Allen

      There is a discussion of putting Java on the iPhone/iPod touch over at the dev team wiki:

      I believe 1.1.2 has been hacked, and if not, it is at least downgradabe.  The instructions (or links to instructions) for jail-breaking and building the toolchain can also be found at the wiki.

      I'm not much good with the low level stuff, but I can probably help implement some of the higher level stuff like wrappers for UIKit.

      • J.L. Allen
        J.L. Allen

        By the way, for the link I posted earlier, SourceForge forum software included the period in it...here it is again without punctuation following it:


        Hopefully this one will work.

    • Wes Biggs
      Wes Biggs

      I was able to cross-compile for arm-apple-darwin, but don't know quite enough about the JamVM/Classpath hookup to know what I'm missing, or if I've correctly compiled one or either.

      Details of my hacking are on the Talk:IPhone_Java page linked above.

      What files do I need to copy over to the iPhone (or in my case it's an iPod Touch, but should be no different)?

      To date I tried copying over the jamvm binary, its classes.zip, and the GNU Classpath glibj.zip.

      Rob, can you help diagnose:

      # ./jamvm -Xbootclasspath:glibj.zip:classes.zip Test
      Error initialising VM (initialiseMainThread)
      Check the README for compatible versions of GNU Classpath
      # ./jamvm -Xbootclasspath/c:glibj.zip -Xbootclasspath/v:classes.zip Test
      Exception occurred while VM initialising.
      java/lang/NoClassDefFoundError: java/lang/Thread

      (It's definitely there in glibj.zip)

      jamvm mods as follows...

      1. add this line to "configure" (line 2559):
      arm-apple-darwin) host_cpu=arm host_os=darwin libdl_needed=no ;;

      2. create a directory os/darwin/arm and copy os/bsd/arm/* into it. 

      3. cd os/darwin/arm, then edit the Makefile to change directory references from os/bsd/arm to os/darwin/arm

      4. Edit callNativeOABI.S.  Change "callJNIMethod" to "_callJNIMethod" (2 locations).  Remove or comment out the line that starts ".type".

      5. configure with arm-apple-darwin and make.

      YMMV -- my build platform is i686-pc-cygwin.

      • dljava

        Mmm, seems like my previous post didn't go thru so I'll try again:

        Great to see more interested in porting Java to the iPhone than just complaining about Apple. I've been attempting it with Kaffe 1.1.7 since the summer when the toolchain effort was started dealing mostly with toolchain issues but it now seems stable enough but I've yet to be successful (bus error at runtime).

        I've gotten the cross compuile to work (initially using a OS X (PPC) then switched to Linux (Fedora) on i686) - one thing I'd recommend is to use an older snapshot and not the bleeding edge since the toolchain is always a moving target (the __eprintf issue is toolchain related) and always check it by building and running the native UIHello sample app. Also, you may also want to use an earlier version of gnu classpath. Any issues cross-compiling classpath?

        I'll going to continue with Kaffe 1.1.8 as well as jamvm (yes I also edited the configure file to get past that host issue) but I'm currently getting the following:

        I../../src -I../../src/interp/engine -I../../src   -g -O2 -MT direct.lo -MD -MP -MF .deps/direct.Tpo -c -o direct.lo direct.c
        mkdir .libs
        /usr/local/bin/arm-apple-darwin-gcc -DHAVE_CONFIG_H -I. -I../../src -I../../src -I../../src/interp/engine -I../../src -g -O2 -MT direct.lo -MD -MP -MF .deps/direct.Tpo -c direct.c  -fno-common -DPIC -o .libs/direct.o
        mv -f .deps/direct.Tpo .deps/direct.Plo
        /usr/local/bin/arm-apple-darwin-gcc -g -O2    engine/compute_relocatability.c   -o engine/compute_relocatability
        engine/compute_relocatability.c:24:17: error: jam.h: No such file or directory
        engine/compute_relocatability.c:25:22: error: inlining.h: No such file or directory

        As if configure isn't inserting the proper includes (weird since it works fine when not cross compiling). Anyone else see this?

        I'll try to be on irc://irc.osx86.hu/iphone


    • Wes Biggs
      Wes Biggs

      And slightly worse:

      # ./jamvm -Xbootclasspath:classes.zip:glibj.zip Test
      zsh: bus error  ./jamvm -Xbootclasspath:classes.zip:glibj.zip Test

      • Wes Biggs
        Wes Biggs

        Sorry, I should be more -verbose:

        # ./jamvm -Xbootclasspath:classes.zip:glibj.zip -verbose Test
        [Loaded java/lang/Object from glibj.zip]
        [Linking class java/lang/Object]
        [Loaded java/io/Serializable from glibj.zip]
        [Linking class java/io/Serializable]
        [Loaded java/lang/reflect/Type from glibj.zip]
        [Linking class java/lang/reflect/Type]
        [Loaded java/lang/reflect/AnnotatedElement from glibj.zip]
        [Linking class java/lang/reflect/AnnotatedElement]
        [Loaded java/lang/reflect/GenericDeclaration from glibj.zip]
        [Linking class java/lang/reflect/GenericDeclaration]
        [Loaded java/lang/Class from glibj.zip]
        [Linking class java/lang/Class]
        [Loaded java/lang/Runnable from glibj.zip]
        [Linking class java/lang/Runnable]
        [Loaded java/lang/Thread from glibj.zip]
        [Linking class java/lang/Thread]
        [Loaded java/lang/VMThread from classes.zip]
        [Linking class java/lang/VMThread]
        [Loaded java/lang/Comparable from glibj.zip]
        [Linking class java/lang/Comparable]
        [Loaded java/lang/CharSequence from glibj.zip]
        [Linking class java/lang/CharSequence]
        [Loaded java/lang/String from glibj.zip]
        [Linking class java/lang/String]
        [Loaded java/lang/Cloneable from glibj.zip]
        [Linking class java/lang/Cloneable]
        [Created primitive class char]
        [Created array class [C]
        zsh: bus error  ./jamvm -Xbootclasspath:classes.zip:glibj.zip -verbose Test

        • Robert Lougher
          Robert Lougher

          Hi Wes,

          I think you've made some really good progress.

          From the verbose output, I'd say that JamVM is crashing when it tries to call a native JNI method (it is about that stage in the initialisation where the first Classpath native method is called).

          It will be useful to try adding -verbose:jni

          This usually means the code which handles the calling-convention is not correct (callJNIMethod).

          Firstly I notice you modified callNativeOABI.S?

          This implies the symbol __ARM_EABI__ is not defined (else you would have needed to modify callNativeEABI.S).

          The thing is, I find it difficult to believe the iPhone can be using OABI.  So either the iPhone is using EABI, but the symbol isn't defined, or it's using another ABI altogether.

          Of course, this could be a slightly modified version of OABI or EABI.  This is what they did with Mac OS X/i386.  It's identical to the Linux/SysV ABI, apart from 8 byte stack alignment.

          Assuming it's not EABI (try forcing it to use callNativeEABI.S), the next stage is to work out what the ABI is.  When I've been in this situation, the easiest way is to simply write a load of test C functions, passing and returning various parameters, and then use gcc -S to examine the assembler output.

          Once you've worked out what it is, you can then modify callNativeXXXX.S...

          Alternatively the iPhone may have libffi.  In this case the job is done.  Just configure JamVM to use libffi to handle the calling-convention (add --enable-ffi to the configure line).  However, this is unlikely.

          Hope this helps,


          • dljava

            Hello Rob,

            Wes and I were working together over IRC (are you free later tonight?) and we are basically at the same point as I got same output using kaffe - right up to the JNI call.

            I also got the following crash dump (thanks Wes for pointing it out):
            Exception Type:  EXC_BAD_ACCESS
            Exception Codes: KERN_INVALID_ADDRESS at 0x3014d000
            Crashed Thread:  0

            Thread 0 Crashed:
            0   libkaffevm-1.1.7.dylib              0x000aab2c 0x7e000 + 183084
            1   libkaffevm-1.1.7.dylib              0x000a8ba0 0x7e000 + 175008
            2   libkaffevm-1.1.7.dylib              0x00099fb4 0x7e000 + 114612
            3   libkaffevm-1.1.7.dylib              0x0007fd5c 0x7e000 + 7516
            4   libkaffevm-1.1.7.dylib              0x000c7fb4 0x7e000 + 303028
            5   kaffe-bin                           0x0000305c 0x1000 + 8284

            I've been trying to get -vmdebug on kaffe working to no avail (probably also due to the same calling convention issue) in order to get some better debug data (to confirm it's jni).

            I believe it is OABI or a variation thereof (I tried installing libffi but couldn't get it recognized and gave up on it - anyone familiar wiht libffi should we pursue it?)

            Would analyzing the UIHello cross-compiled example that we both got running help?


    • Robert Lougher
      Robert Lougher


      Sorry, I've been busy in work for the last few days. I'll try to catch up tomorrow.


    • Wes Biggs
      Wes Biggs

      Don't know if any of this is helpful, but I built jamvm with --enable-trace (BTW there are a couple of TRACE lines in src/dll.c in vanilla 1.5.0 that I had to add commas to, in order to fix syntax errors).

      The last output before the bus error is this:

      Preparing java/lang/Object.<init>()V
      0 : pc 0 opcode 177 cache 0

      Am I right in thinking this has to do with some linking issue?


    • Robert Lougher
      Robert Lougher


      Just to let everybody know that I now have an iPhone toolchain, and a jailbroken UK iPhone.  This means I should be able to work much more closely on getting JamVM working.


    • I actually got this working last night. I've gone ahead and updated the wiki page with the instructions: http://iphone.fiveforty.net/wiki/index.php/IPhone_Java .

      The patches to the JamVM are all to be found at http://test.saurik.com/iphone/jamvm/, along with a tar of the binaries you would need to extract onto your phone to make it all work. No patches were required for GNU Classpath: it worked out of the box.

      The commands (and patches) required to make JamVM work were as follows:

      wget -qO- http://test.saurik.com/iphone/jamvm/\{ambiguous,arm-apple-darwin,tracing}.diff | patch -p1
      ln -s ../linux/arm src/os/darwin
      CFLAGS=-O0 ./configure --host=arm-apple-darwin --prefix=/usr --with-classpath-install-dir=/usr
      make install DESTDIR=$(pwd)/../jamvm-iphone-1.5.0

      The one thing that's still sketchy is that it _does not_ work if I optimize the build. I haven't had the time to figure out where this is broken yet. It might be any or all of the llvm-gcc, odcctools, jamvm, and classpath ;P.

      • dljava

        Hello Jay, congrats. What platform did you build on (latest toolchain?) Haas anyone confirmed if the odcctools patches are necessary?

        Could you summarize the changes? So it was the JNI calling convention for EABI the issue?


        • I compiled it from amd64 Debian with the latest toolchain (although, AFAIK, the toolchain hasn't been updated in at least a month). I did not follow the instructions for setting up the build environment, though, as those instructions are A) for Mac OSX, B) destroy your local build environment (the instructions actually encourage you to edit your local system headers...), and C) misuse the cross-compilation flags on gcc. :( That, combined with the odcctools patches I have, means that I wouldn't be horribly surprised if the build didn't work for someone else right out of the box. However, I seriously doubt that anything I changed made a difference there.

          As for what I did to JamVM, I thought the diff was somewhat clear (arm-apple-darwin.diff only has three short changes). EABI definitely wasn't the problem as the iPhone uses OABI. ;P

          Here's an english summary of arm-apple-darwin.diff:

          1) I had to add support for arm-apple-darwin to the configure script so it would even allow the build to take place
          2) I needed to add an #include for <string.h> to one of the files as it wasn't getting something (strlen maybe?)
          3) the 3rd party iPhone assembler doesn't support .type, so you have to manually add the _ to the beginning of the callJNIMethod symbol

          The other two patches (ambiguous.diff and tracing.diff) fix bugs I found in JamVM's source code as I went through the process of clicking everything together. The first fixes an issue that's something like   *a++ = a[-1]   (which is definitely ambiguous and generates a warning on my compiler), although I'm not 100% certain I corrected it right, at least what I did was one of the possibilities for what the compiler would have chosen before... I didn't stare at it for too long. The second adds some missing ,'s to a few calls to TRACE() so that they compile (I had tracing on for a while). I might should just remove those two patches from the instructions on the wiki.

          I haven't carefully read through the other posts on this thread to see what other people were doing and why it didn't work. (I didn't know this thread existed until today, and I got it working yesterday, so it didn't seem to matter and there were a lot of posts. ;P) I did see your progress on JamVM on the talk page of the wiki, but at the time I was much more interested in trying to get JamVM working with Apache Harmony's class library, so the mention of GNU classpath made me keep looking, and then I didn't get back to it until after I tried classpath and it worked ;P.

          If anything, I would imagine the thing that caused the most frustration is the fact that optimization seems to break the build. You really need that CFLAGS=-O0 or it bus errors. I was lucky in finding that as, when I first started, I wasn't using the JamVM build environment at all, and I hadn't bothered putting in any -O flag at all. Here's the command I ended up with before I started working on getting things done inside the JamVM build environment:

          arm-apple-darwin-gcc -O0 -Wall -Werror -o jamvm -lz src/os/darwin/*.c src/os/linux/arm/*.c \     -Isrc src/*.c \     -Isrc/interp src/interp/*.c \     -Isrc/interp/engine src/interp/engine/!(compute_relocatability).c \     -x assembler-with-cpp <(sed -e 's/callJNIMethod/_callJNIMethod/g' src/os/linux/arm/callNativeOABI.S | grep -v '\.type')

          I then only bothered to make things work with the JamVM build environment as I went back to the wiki, re-saw your post, and realized "ok, so using the JamVM build environment isn't a lost cause, and people will probably appreciate it more than running some funky command to build the code". ;P But then it started to "bus error". It took another ten minutes or so of examining differences and I noticed the -O2 and isolated that as the breaking issue.

          If you'd like to talk to me via AIM, by the way, feel free. I'm "saurik" on there. I'm also on the iphone IRC channel (have been lurking for the last month), but don't really check it at all (even private messages). I quite often look at irc.saurik.com, though (#saurik is probably where you would want to look).

      • Ok, so I've noticed some people are using a shell that doesn't support command alternation, and wget is actually trying to download a single file with {}s from my server. :(

        If that's the case, you need to do this instead:

        wget -qO- http://test.saurik.com/iphone/jamvm/ambiguous.diff | patch -p1
        wget -qO- http://test.saurik.com/iphone/jamvm/arm-apple-darwin.diff | patch -p1
        wget -qO- http://test.saurik.com/iphone/jamvm/tracing.diff | patch -p1

        I've updated the wiki to use these instructions.

    • Wes Biggs
      Wes Biggs


      This is really exciting.  Glad to see the iPhone Java hacking picking up steam!


    • Robert Lougher
      Robert Lougher


      Thanks to everybody who's been experimenting with this.  I've now got JamVM up and running on my iPhone.  Some screen dumps can be found here:


      This shows the usual HelloWorld, and a couple of screenshots running Jetty, a Java-based web application server.  This is running in about 20MB, and is using 39 threads.

      As saurik discovered, JamVM will only run when compiled with -O0.  I spent some time debugging this, and I'm confident it's a toolchain issue.  The interpreter is one extremely large and complex function, and I expect the LLVM optimiser is blowing up somewhere (using printfs, I tracked the first bus error down to a null pointer dereference; however, printfs show the variable contained the correct value before a call, and null immediately afterwards; this indicates live variables aren't being correctly preserved across calls).

      Unfortunately, this means it's running 2/3 times slower than fully optimised.  Hopefully, newer versions of the toolchain will fix this.

      For the record, the changes required are:

      1) Add arm-apple-darwin to supported architecture list in configure.ac, and add a line to output the Makefile for src/os/darwin/arm (you then need to run automake; autoconf).

      2) Copy src/os/linux/arm to src/os/darwin

      3) Edit callNativeOABI.S and remove the line beginning with .type, and add _ to callJNIMethod (two times).

      BTW, the calling convention the iPhone is using is a modified OABI.  It appears to use r7 as a frame-pointer, which points to the previous value of r7.  However, by luck JamVMs OABI routine works, as it doesn't use or corrupt r7 (this isn't the result of the bus error as I first thought, it crashes before).

      I will check the required changes into CVS on the weekend.  This means the CVS version should work on the iPhone "out of the box".

      As the ARM processor is an ARM11, it's using architecture ARMv6.  This supports the new atomic instructions.  Currently, JamVM uses swap for compatibility with ARMv4/v5.  If I get the chance I'll also experiment with changing this.  However, I doubt it'll make much difference.



    • Aslak Knutsen
      Aslak Knutsen

      Nice work guys!

      I've got Jboss 4.2.1(minimal) running on my iPod Touch using this JamVM version.

      I tried getting GridGain working so I could make a grid out of my iPhone and iPod Touch, but no luck so far. After commenting out some java checks in the startup script i failes with:

      Caused by: java.lang.IllegalStateException: GridGain requires Java 5 or Java 6. Current Java version is not supported: 1.4

      Checking the GridGain source shows it uses the System property java.specification.version. Setting the system property on startup -Djava.specification.version=1.5 results in a native call problem while creating the platform MBeanServer.

      java.lang.UnsatisfiedLinkError: getMemoryPoolNames
         at java.lang.management.VMManagementFactory.getMemoryPoolNames(Native Method)
         at java.lang.management.ManagementFactory.getMemoryPoolMXBeans(ManagementFactory.java:397)
         at java.lang.management.ManagementFactory.getPlatformMBeanServer(ManagementFactory.java:510)
         at org.gridgain.grid.GridFactory$GridNamedInstance.start(GridFactory.java:824)
         at org.gridgain.grid.GridFactory.start0(GridFactory.java:536)
         at org.gridgain.grid.GridFactory.start(GridFactory.java:394)
         at org.gridgain.grid.loaders.cmdline.GridCommandLineLoader.main(GridCommandLineLoader.java:287)

    • Steve Dawson
      Steve Dawson

      why can't i see the window after run the application HelloJava which was got from the iphone/java package.
      there is a process named jamvm in the system processes ,when i start it in terminal window ,it didn't report any error.
      Who can give me some advises?

      • The most important thing to note is that you can't run iPhone applications from the Terminal: SpringBoard notices that it didn't start the program and kills it. You should read the developers FAQ in Cydia for more general information about installation of iPhone applications, the limitations Apple has implemented, and the workarounds we have in place for them.

  • Bill Pay
    Bill Pay

    Thanks for giving the information. Its very helpful for me.

    Bill Pay

1 2 > >> (Page 1 of 2)