Works great for me, what obstacles remain?

1,655 views
Skip to first unread message

Simon Robinson

unread,
Jun 17, 2013, 5:37:18 AM6/17/13
to rob...@googlegroups.com
So I've spent a week playing with RoboVM snapshot 0.0.3 getting to know it and for our use case it seems to be working well.
We have a large mixed up Java codebase, mostly a desktop app, which has been for a long time directly integrated to an Android app, with a normal Android frontend attached. The iOS port has always been difficult so I considered if RoboVM was a valid way to convert our java core logic to an iOS library to sit behind our iOS frontend.

RoboVM's objective C and UIKit bindings are great so far, but the iOS UI world is a fast moving place that doesn't always behave logically (e,g, iOS 7 beta), so I consider a normally built objective-c UI frontend to be the right way for us.

I was able to get this going - the object file list that robovm uses for linking the final application, works as the input for linking my normally written XCode iOS app. I currently let the java code provide the main() method and the Delegate class but I forward its calls always to objective C, via native/JNI style calls. And I have some simple interactions going the other way from objective-c to java via the JNI again. 

So building our app this way is looking very promising. I wonder if anyone can suggest what other obstacles and gotchas exist, that might hurt me on the road to getting this sort of app into the AppStore?
I am going to certainly investigate things like:
- memory usage of our core
- battery usage
- binary size - it is big so far but actually not too big
- performance already looks OK

The only real annoyance so far are a few ICU errors, and I am sure there is a way around that with time (maybe I continue hacking those problems out on the java side?),

The overall question is, what does "not production ready" mean... :)
Perhaps my use case where the robovm core is the most important to me is a bit different too. Hey it already compiles 2000+ java classes of mine (and third party jars) with no complaints. (I am impressed)

cheers,
Simon

Niklas Therning

unread,
Jun 18, 2013, 11:14:28 AM6/18/13
to Simon Robinson, rob...@googlegroups.com
Wow, this is very cool! I'm impressed. This is not what RoboVM has been designed to do but I guess you've already figured that out. :-)

There are a few things missing before I would consider RoboVM "production ready":
 * Performance optimizations. E.g. invokevirtual/invokeinterface are currently done using a linear search on every call! There's a milestone in Github for this: https://github.com/robovm/robovm/issues?milestone=2&state=open.
 * The ICU mess has to be sorted out. https://github.com/robovm/robovm/issues/81
 * Testing. Real apps need to be developed and tested. (beta testing)

And then the tools need to be able to produce signed archives that can be submitted to the app store (doesn't apply to you of course since you're using Xcode).

If the performance is acceptable for you and you don't find issues while you investigate the points on your list I think you should go for it and try to get it into the app store. Please keep us updated. It will be very interesting to see what Apple says. I don't expect any problems but you never know with Apple. :-)

/Niklas


--
You received this message because you are subscribed to the Google Groups "RoboVM" group.
To unsubscribe from this group and stop receiving emails from it, send an email to robovm+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Simon Robinson

unread,
Jun 25, 2013, 8:07:10 AM6/25/13
to rob...@googlegroups.com, Simon Robinson
Thanks Niklas, looks like we will push forward and see how far we can get with RoboVM. Performance so far seems ok, at a guess we might be hit more by a need to carefully configure Boehm GC to behave well for us as the java code we have is sometimes sloppy with memory. If we get as far as trying to get some RoboVM code into the App Store we will have to let you know.

Have I overlooked anything regarding the Bro native bridge - it appears to be inappropriate for accessing statically linked code?

Perhaps worthy of a feature request is support for java assert statements - if I can turn these on then I will feel more confident about the correctness of our converted java code. 

I guess as long as Class.desiredAssertionStatus() returns only false, these assertions are not yet run.

cheers,

Simon

Niklas Therning

unread,
Jun 26, 2013, 9:54:39 AM6/26/13
to Simon Robinson, rob...@googlegroups.com
Bro can't call into static code at the moment but we'll have to make this possible eventually. Shouldn't be too hard. The executable needs to export the symbols that should be callable and there has to be a way for Bro to bind to the current executable (dlopen(NULL)), e.g. @Library(SELF). I don't think there's an issue for this on Github. Please add one if you'd like to see this in RoboVM.

Please add an issue for adding asserts.

Kurayami Tenshi

unread,
Jul 23, 2013, 1:24:29 AM7/23/13
to rob...@googlegroups.com
Hi Simon
I have a similar use case too and I've just started evaluating RoboVM for this purpose.
Can you give some pointers about how I should get around to doing it?

Thanks!

Regards
Angel

vin...@gmail.com

unread,
Aug 2, 2013, 10:13:26 PM8/2/13
to rob...@googlegroups.com, Simon Robinson
Hi Simon/Niklas,

I have an immediate need for using a Java library via RoboVM in a native ObjC app. I'm new to RoboVM so I'd be grateful if you could share how you achieved it and what's the status for making it easy on RoboVM. If help is needed we'll be happy to contribute.

The idea is to create a cross-platform Java library that is usable on both iOS and Android, so that only a single codebase is maintained.
As the users of this Java library are companies with existing ObjC apps, it is not possible (nor necessary) to ask them to migrate their app to a RoboVM-based one; what they need is an API produced by RoboVM as a static library for use in their existing app.

Thanks in advance for any advice!

Vin

Niklas Therning

unread,
Aug 3, 2013, 1:44:12 AM8/3/13
to vin...@gmail.com, rob...@googlegroups.com, Simon Robinson
Did you have a look at J2ObjC? Maybe it will suit your needs better?

Vin Kemp

unread,
Aug 20, 2013, 7:30:10 AM8/20/13
to Niklas Therning, rob...@googlegroups.com, Simon Robinson
Thanks for the tip! It looks promising. I'm going into look into it pretty soon and will report back on how well it worked for me.

Simon Robinson

unread,
Aug 21, 2013, 3:05:32 AM8/21/13
to rob...@googlegroups.com, Niklas Therning, Simon Robinson
Time is always short for me and we aren't playing much with RoboVM right now, but I have a process in place which I should share.
FYI when I looked at j2objc I like the intent behind it, but seeing they've chose not to support quite everything - specifically object.wait() and notify() can not be called, the interaction with the synchronized keyword was not precisely implemented. (Unless that has recently changed).




+++++++++++++++++++++

 key steps to getting RoboVM in use as a library to sit behind a nice traditional Xcode-objc app.

I understand that its not Niklas' focus but its certainly not difficult and down the line it will make a great use case. In fact it is reasonably complex, if you are not comfortable configuring XCode to compile a slightly complex project, then this might be too much for you. I cannot offer support really if you have trouble with this process, but it would be nice to see other people being able to do the same thing.


Step 1- build your java library

--------------------------------------------------


- I code the main(String[] args) in Java. I think it is required. Example

class MyJavaRoboCode {

public static void main(String[] args) {

        NSAutoreleasePool pool = new NSAutoreleasePool();

        // initialize java objects, you can initialize native / JNI too

  // here…

        // …

        // Then trigger my normal iOS app delegate

        UIApplication.main(args, null, Delegate.class);

        pool.drain();

}


// Corresponds to MyAppDelegate.m in my xcode project

@NativeClass("MyAppDelegate)

public static class Delegate extends UIApplicationDelegate.Adapter {

}



private static final native void nativeInit();

public static void callJava(String arg) {

  System.out.println("Java was called from native with arg " + arg);

}

}


Step 2- Code the native side that you mix into your traditional nice XCode project.

--------------------------------------------------

- the native side of the JNI is written in a c++ file to be added to XCode

- we bridge to and from java here: brdige.cpp =


#include <stdio.h>

#include <string.h>


#include "robovm.h"

#include "robovm/exception.h"

#include "robovm/method.h"


extern "C" {


void Java_com_blah_JavaMain_nativeInit(Env* env, Class* c);

void Java_com_blah_JavaMain_nativeInit(Env* env, Class* c)

{

printf("In native\n");

JNIEnv* jniEnv = &(env->jni);

// Do things with jniEnv - e.g. lookup classIds and methodIds in java, and

// Save them to be used later. Or do whatever you want.

}

}


void callSomethingInJava(const char* arg)

{

// To call into java from your native app, use JNI

Env* rvmEnv = rvmGetEnv();

JNIEnv* jniEnv = &(rvmEnv->jni);

jclass myJavaClass = jniEnv->FindClass("com/mine/MyJavaRoboCode");

jMethodID myJavaMethod = jniEnv->GetStaticMethodID(myJavaClass, "callJava", "(Ljava/lang/String;)V");


jstring argAsJavaString = jniEnv->NewStringUTF(arg);

jniEnv->CallStaticVoidMethod(myJavaClass, myJavaMethod, argAsJavaString);

}


--------------------------------


The robovm headers necessary for compiling the JNI code are found in the RoboVM source repo:

vm/core/include

So add this to your xcode include paths.


I have found one header is missing and referenced from vm/core/include/robovm.h 

gc.h is not found? (I havent looked into it, perhaps its just found in a different folder).

This header for the moment appears to not be required - I modified vm/core/include/robovm.h and removed the reference to it.



So, you have the native side, you have the java side, you need your nice normal XCode app to compile your JNI native code and of course link with the outputs of JVM. This can be done…


1. RoboVM must be set up normally, and your java code should be put into a normal RoboVM project as the main class. It should be compilable, but it wont run as it depending upon the XCode application for the main app delegate.


2. We run RoboVM from the command line so that we can parse its output. Make a script as follows:


arch_and_target_args="-arch x86"

exe_outdir=./temp_simu_exe

target_static_lib=./my_robo_simulator_lib.a


robovms_classpath=/opt/robovm/lib/robovm-objc.jar:/opt/robovm/lib/robovm-cocoatouch.jar

my_custom_classpath=bin

command="/opt/robovm/bin/robovm -verbose -properties robovm.properties -config robovm.xml ${arch_and_target_args} -d ${exe_outdir} -cp ${robovms_classpath}:${my_custom_classpath}"

echo Executing: $command


store_robo_compile_output=.last_robo_compile_output

# rm old output incase new call fails or screws up

rm -f $store_robo_compile_output

$command | tee $store_robo_compile_output


# The magic of SED gets us the OBJECT filelist, and also the exported symbol list, out of robovm's compile log

objectsListFile=$(cat $store_robo_compile_output | grep -- '-Wl,-filelist,' | sed -e 's/^.*-filelist,\([^ ]*\) .*/\1/')

exportedSymListFile=$(cat $store_robo_compile_output | grep -- '-exported_symbols_list' | sed -e 's/^.*-exported_symbols_list \([^ ]*\) .*/\1/')



# Those live right now in a temp directory, copy them locally

target_objects_file=$target_xcode_project_dir/compiled_simulator_objects.list

target_exp_symbols_file=$target_xcode_project_dir/exported_simulator_symbols.list


cp "$objectsListFile" "$target_objects_file"

cp "$exportedSymListFile" "$target_exp_symbols_file"


# Optional - we can archive the objects into a static library now, or tell XCode to use that object file list directly

libtool -static -o ${target_static_lib} -filelist ${target_objects_file}



3. If the script above is good, it will run robovm for us, and parse from the final step of RoboVM which is when it compiles the final app.

From there we just want the object files robovm has built, we take therefore the object_file_list from the output, and feed this later into XCode.

Optionally we can make a static lib from the object files with the libtool call.



The next step is to configure XCode to link in the RoboVM magic correctly.

Configuring XCode is always a lot of fun, the best way in my opinion is


- Add the compiled static library to the project (my_robo_simulator_lib.a)

- Set linker flags so XCode compiles the rest of the robovm runtime in. E.g. For targeting Simulator:


 -L "$(ROBOVM_VM_DIR)/x86"

 -Wl,-no_implicit_dylibs -Wl,-dead_strip -lrobovm-bc

 -force_load "$(ROBOVM_VM_DIR)/x86/librobovm-rt.a"

 -lrobovm-core -lgc -lpthread -ldl -lm -lstdc++ -liconv -lsqlite3

 -exported_symbols_list exported_simulator_symbols.list


(These are flags copied from the output of RoboVM's normal compile. Be careful if you change them, you might break something)

(ROBOVM_VM_DIR is an Xcode env variable I set currently to /opt/local/robovm/lib/vm/ios)



4. Extra step - RoboVM collects your java resource files into jars which are placed in the output application,

in our case they should end be in temp_simu_exe/lib

- Add or copy or otherwise link this lib directory to your XCode project



5. Compile & Run in XCode! (Phew, was that worth it?)

- try adding breakpoints to your jni bridge code, see calls going into and out of the java. 

- watch out for general JNI challenges - exceptions etc.

This is for iOS simulator, and so for the device build you need to obviously re run robovm with thumbv7 arch, consider sending output

to a different set of a files, different library etc. Dont forget the linker flags in XCode must match the device target, you can

fortunately tell XCode to use different linker flags for device vs simulator target… fun fun

+++++++++++++++++++++

Matti Vilola

unread,
Aug 29, 2013, 4:20:32 AM8/29/13
to rob...@googlegroups.com
Hi Simon, Niklas et co.

Thanks for the information you have shared.. I would like to come back to Simon's original question and status re: RoboVM "not production ready": may I ask where are we standing right now and what is in the pipeline at the moment?

I have successfully set up the build environment for my libGdx projects to work with RoboVM and so far looks darn good. I have been able to port and utilize my existing application codebase and run the apps in iOS simulator and device. So far I have tested and investigated performance, memory footprint and binary sizes which all look relatively good to me. I am impressed! 

What remains to be solved, in order to push libGdx based app to AppStore, is at least following:
- audio: how is the work ongoing with ObjectAL integration?
- input: orientation handling, keyboard bindings: haven't tested with latest; how are we doing with these?
- package deployment to AppStore: a tool to generate proper package including icons&properties information that can be uploaded to AppStore e.g. via Apple's Application Loader. I am not so familiar with the structure of this package and going into a production mode would require definitely such (automated) tool (--> not a showstopper, eventually I would need to learn&create one myself)
- and of course, touch working on simulator and improved debugging would be nice-to-have from developer's perspective but really hey: this is not stopping the flow.. ;)

Next steps for me is to integrate platform related functions/libraries to iOS side as well in order to align features similar to what I have in desktop/Android side.

Any status updates available? All comments appreciated. Thanks in advance!

Niklas Therning

unread,
Aug 29, 2013, 5:20:47 AM8/29/13
to Matti Vilola, rob...@googlegroups.com
Hi Matti,

I'm working on some performance improvements at the moment. Typechecks (checkcast/instanceof) and virtual/interface method dispatch have been greatly improved. Should make it into tonight's nightly build. I'll release 0.0.4 shortly.

"production ready" includes:
* App Store builds - signed archives that can be submitted to App Store. As Simon has shown it is possible to do this using Xcode already though messy.
* iOS7 support
* iOS7 cocoatouch bindings - A tool that can create these bindings automatically is in the works but currently stalled.
* Fixing the ICU mess. This is related to iOS7 support since the current ICU hack doesn't work or work badly with iOS7.
* Testing

As for libgdx audio is AFAIK what remains for the RoboVM backend to be complete. Orientation changes are implemented I think (at least the screen rotates when I test superjumper on my iPhone). And touch in the simulator isn't working. Don't know about keybindings.

I had a quick look at how audio is implemented in the libgdx Monotuch backend and it shouldn't be too hard to create bindings for the few things in ObjectAL that are required. If you would like to give it a shot I'll be happy to help you out. The same tool mentioned above should be able to generate these bindings automatically later on but for now manually is the way to go.

/Niklas



--

Matti Vilola

unread,
Sep 1, 2013, 10:06:43 AM9/1/13
to rob...@googlegroups.com, Matti Vilola
Hi Niklas,

many thanks for your quick response! Sounds good, I'll look forward to check latest nightly build of RoboVM and will also integrate with latest LibGDX builds to see where we are standing. I am continuing the work in this area within following days/weeks after completing my current activity.

As far as I see, the work with IOS 7 is very important incld. cocoatouch bindings. In addition to that, the AppStore builds is of course key factor in getting the first apps out there for Apple to review. I will check the audio thing status with Mario and then based on the status/comments, might be able to allocate some time in this as well even not being too familiar on the subject. From my projects' perpective, I would be able to submit an application to AppStore immediately once we have these issues solved in order to validate proof-of-concept with this method.

It would be highly appreciated if you would be able to share your thoughts about the timeline for "production ready" from your perspective? Any "guestimate" for such? 

Br,
Matti

Niklas Therning

unread,
Sep 7, 2013, 4:04:15 AM9/7/13
to Matti Vilola, rob...@googlegroups.com
I'm starting to regret the "production ready" term I've been using. :-) If it works for you (with a lot of testing) then go for it.

I will release version 0.0.4 some time next week. This release is as far as I know pretty ok. I've made some changes to make it work on iOS 7 and it works (tested with the superjumper libgdx sample app). The major improvement with this release is performance. In particular method dispatch is now a lot faster. I've also turned on LLVM optimizations (roughly corresponding to -O2 when you compile C/C++ with clang). I will publish some benchmarks later this month I hope.

If your app depends a lot on localization (DateFormat, NumberFormat, normalization, collation, etc) you may want to wait for the ICU issues to be sorted out. As you may have seen on Twitter or the libgdx blog we've added audio support to the RoboVM-based libgdx backend. So, if localization isn't a concern for you and if everything seems to work with the latest libgdx and RoboVM (I recommend a lot of testing! :-) ) I think you should go for it. I will talk you through the packaging for App Store procedure. It will be the first time so this is very exciting (and you should expect some road bumps ;-) ).

Matti Vilola

unread,
Sep 7, 2013, 5:20:23 PM9/7/13
to rob...@googlegroups.com, Matti Vilola
Haha.. understood your comment with "production ready" :D

Many thanks for the status update, me/we are looking forward for the next release!

Meanwhile I will focus on setting up the necessary steps for the first iOS release with some missing platform related integration to be done (as well as certain packaging stuff). The audio fix is very important and I will be testing it next week and after that continue with this stuff. The localization functionality with ICU issues are currently not so relevant for our (simple) production/apps.

So very interesting indeed.. please let me study the AppStore packaging first myself and I'll then set up a new forum thread if I encounter any issues with it (with supporting documentation) and of course, can anyway update you on the progress. Thanks for the support!

Best regards,
Matti

Tom Ball

unread,
Sep 17, 2013, 6:24:34 PM9/17/13
to rob...@googlegroups.com, Niklas Therning, Simon Robinson
Very recently -- wait/notify/notifyAll support was pushed publicly the day before you sent this. :-) 


Last week we pushed full java.lang.ref support, another gnarly compatibility issue (though at the rate Niklas is coding, it's probably already done in RoboVM!).

Simon Robinson

unread,
Sep 18, 2013, 2:49:38 AM9/18/13
to rob...@googlegroups.com, Niklas Therning, Simon Robinson
Nice to hear that Tom, j2objc is then a very useful tool to have in our arsenal as well.

RoboVM however continues to work better than most people would expect. 0.0.4 looks good to me, my script and parse approach above for generating a static library out of robovm code still work, thanks Niklas!

For some reason however the "strip" command on my libraries doesn't have any useful effect anymore, but I will look into that later.
Simon
Reply all
Reply to author
Forward
0 new messages