Open source Java iOS tools compared

Java programming for Apple's iOS devices is not only possible but it's getting easier all the time. Steve Hannah surveys the recent evolution of the Java iOS landscape, then introduces five open source Java iOS tools. Find out how Avian, Codename One, J2ObjC, RoboVM, and XMLVM resolve the challenges of Java iOS native client development for developers who are ready to go mobile. (Includes an introductory section on garbage collection vs reference counting in Java iOS application development.)

FEATURED RESOURCE
Presented by Attachmate

This paper discusses both new and traditional approaches to legacy modernization, while highlighting a

LEARN MORE

As a Java developer I have felt somewhat excluded by the wall around Apple's iOS garden. Until recently, if I wanted to write an application for an Apple device such as the iPhone or iPad, it meant leaving the Java ecosystem behind and coding in Objective-C. The barriers to entry were both political and technical, but Apple's decision in September 2010 to relax the restrictions on its development tools effectively dissolved the political constraints. Since that announcement, a handful of open source solutionshave emerged that allow developers to write iOS applications in Java. I briefly introduce five of those tools in this article:

  1. Codename One
  2. RoboVM
  3. Avian
  4. XMLVM
  5. J2ObjC

Each of these tools can be used to write Java code that can be run directly on an iOS device natively. I omitted the myriad of server-side Java EE solutions that publish HTML5/CSS/JavaScript applications to a Web browser or similar client on the device. There's enough to say about tools in this category for another complete review. Note, too, that Oracle has recently announced its intention to open source the iOS versions of JavaSE Embedded and Java FX. Both of these platforms are potentially viable pathways from Java to iOS, especially when combined with the recently announced proposal to enhance the JNI specification with support for statically-linked native libraries.

Strategies for running Java on iOS

Three categories of tools allow Java developers to write to iOS devices:

  1. Server-side technologies (such as VaadinTabris, andICEmobile) run Java code on a server and publish either HTML5/CSS/JavaScript or JSON to be rendered on the device via a web browser.
  2. Client-side technologies, discussed in this article, run Java code directly on the device using a compile-time conversion to a native binary.
  3. Hybrid technologies like Oracle ADF deploy both server-side and client-side Java components.

The client-side tools profiled in this article are especially geared to creating native Java apps that run on iOS devices such as the iPhone and iPad. They enable developers to write code in Java that is then compiled into a native iOS binary. Although their user interface and integration strategies vary, each tool provides a native method mechanism that allows you to call Objective-C and C APIs from Java code.

Avian, for instance, uses standard JNI, whereas XMLVM uses its own native method system, which is similar to JNI but provides stronger compile-time validation. RoboVM and XMLVM also provide Java wrappers for many of the iOS APIs (such asUIKit), so that you can develop an entire iOS application in Java without once delving into Objective-C. Codename One solves the user-interface puzzle by providing its own pure-Java lightweight UI toolkit, but it also supports native interfaces that allow you to talk to Objective-C from Java. J2ObjC's answer to native interfaces is similar to GWT's, in that it allows you to define native Objective-C implementations for Java methods inline using OCNI.

Note that this article assumes that you are familiar with the basic architecture of iOS tooling and applications.

Codename One

Codename One provides a full-development toolchain for writing iOS applications in Java. Applications written in Codename One can be deployed to a variety of devices, including Android, iOS, BlackBerry, Windows Phone, and J2ME (although some features may not be available on lower powered devices). Codename One comes the closest of any Java mobile toolkit to supporting Java's "write once run anywhere" premise. Two components are key to enabling it to work across multiple platforms:

  1. Lightweight UI toolkit: The cross-platform UI toolkit is similar to Swing. Codename One UIs are pluggable and themeable, enabling them to take on the look-and-feel of a native device. A Codename One app running on an Android device will match the Android look and feel; on iOS it will match the iOS look and feel.
  2. Pluggable implementation: All of Codename One's platform-dependent code is contained in a single class that can be easily overridden to support another platform. This makes the framework extremely portable. The default iOS port is is currently XMLVM, but it isn't difficult to change it to Avian or RoboVM. (In fact, I created an Avian port as a research exercise without too much difficulty.)

Figure 1 shows a typical path from Java to iOS using Codename One.

The Codename One toolchain
Figure 1. The Codename One toolchain (click to enlarge)

Codename One comprises a Java API, the Codename One Designer tool (a WYSIWYG GUI builder), a simulator that allows you to test your application, and a cloud build server that allows you to build your application for any device. One nice thing about the cloud build server is that you don't need to have proprietary tools such as the Apple developer tools installed. Codename One's build server frees you from the platform dependency typically associated with iOS development. With Codename One, you don't need to have a Mac to develop apps for iOS anymore.

Codename One application architectureFigure 2. Codename One application architecture

It's also possible to set up your own build environment and not depend on the Codename One cloud server. Doing that would entail creating a multi-step build process involving javac, a build tool such as Ant, XMLVM (see below), and Xcode.

RoboVM

RoboVM is brand new (in version 0.0.1 at time of writing) and much of the Cocoa/Objective-C bridge is unfinished, but it appears to be full of potential. RoboVM is a command-line tool that you can use to compile Java .class files into native machine code. It provides an AOT (ahead-of-time) compiler based on LLVM, C bindings, and an Objective-C bridge, which lays the foundation for pure-Java applications to be deployed on iOS. It also includes a full set of Cocoa bindings (which should enable you to use the iOS native APIs directly from Java) and an Eclipse plugin that allows you to compile and run on the iOS simulator directly from Eclipse.

Figure 3 shows a typical toolchain path from Java to iOS using RoboVM.

The RoboVM toolchain
Figure 3. The RoboVM toolchain

RoboVM was designed as a path for Android developers to reuse their business logic code on iOS. You can either create the UI programmatically in Java, or you can use Apple's Interface Builder and Xcode to develop the UI and then copy the Nib file into your RoboVM project and link it up to your Java classes. It includes some nifty annotations that enable you to register Java classes with the Objective-C runtime and register Java methods to respond to Objective-C messages, so that you can define outlets for a Nib file inside a Java class. Figure 4 shows RoboVM's application architecture.

RoboVM application architectureFigure 4. RoboVM application architecture

RoboVM is still very young, so if you decide to try it out you should expect to get your hands dirty with its API. You will likely run into missing methods for which you'll need to generate bindings. All of the tools are present but documentation at this early stage is still scarce, so you may have to go through some cycles of trial and error.

Avian

Avian is a bit of a misfit in this group because it wasn't written to solve the Java iOS problem specifically. Instead, Avian is a lightweight JVM that includes a tool (bootimage-generator) that compiles Java bytecode into native binaries that can be run on ARM devices like the iPhone. Avian's creator, Joel Dice, has published asample iOS application that serves as a proof-of-concept for building iOS applications in Avian.

Figure 5 shows a typical path from Java to iOS using Avian.

The Avian toolchain
Figure 5. The Avian toolchain

Avian doesn't provide specific bindings for iOS native APIs and it doesn't provide special APIs for building mobile applications. Any interaction between Java and the native environment must take place using JNI. Avian includes its own class library that is a more modular and portable subset of JavaSE, but it also allows you to build applications against OpenJDK 7. In order to reduce the size of the resulting binary, Avian uses Proguard to strip out dead code. Figure 6 shows Avian's application architecture.

Avian application architectureFigure 6. Avian application architecture

XMLVM

XMLVM has a much broader focus than most of the other tools discussed here because it aims to allow translation between many different languages. One such translation path is from Java bytecode to C source code, which is used to build iOS applications in Java. The typical XMLVM build process is to write some code in Java, compile it using javac, then use XMLVM to convert the .class files into .h and .c files. These C source files are then added to an Xcode project and built into an iOS application, as shown in Figure 7.

The XMLVM toolchain
Figure 7. The XMLVM toolchain

XMLVM can be invoked from the command-line to perform conversion directly, or it can be invoked to create a skeleton NetBeans project that includes the appropriate libraries and build scripts to compile a Java application for iOS. The "Run" option actually creates an Xcode project with the translated C files, and opens it in Xcode. There you can debug the project, run it on a connected device (iPhone or iPad), or run it in Apple's simulator.

Like RoboVM, XMLVM contains Cocoa bindings that enable you to use native iOS APIs directly from Java, but they have many missing pieces. If you intend to use these bindings you should be prepared to pop the hood and possibly fill in some gaps yourself. Figure 8 shows an XMLVM application architecture using Cocoa wrapper classes for UI.

XMLVM Architecture using CocoaFigure 8. XMLVM application architecture using Cocoa

If you want to include source that has been translated by XMLVM into an existing Xcode project, you can do so, but you will need to take care to add the appropriate build rules and initialization code for the garbage collector. You should also understand the implications of mixing garbage-collected code with reference-counted code. Figure 9 shows an XMLVM application architecture where the Java business logic has been compiled to C and included in an existing Xcode project.

XMLVM compiles a Java app and ports it to an Xcode projectFigure 9. A Java app compiled to C and ported to an Xcode project

J2ObjC

J2ObjC has the narrowest focus of the tools introduced in this article. Open sourced late last year, it was designed by Google specifically to allow code to be shared between Java (Android and GWT) and Objective-C (iOS) projects. Figure 10 shows a typical path from Java to iOS using J2ObjC.

The J2ObjC toolchain
Figure 10. The J2ObjC toolchain

J2ObjC includes a command-line tool for converting Java source code to Objective-C source code. It also includes some Java annotations and a Java compatibility library for Objective-C. J2ObjC's narrow focus makes it an ideal choice if your goal is to share business logic between apps written inJava and Objective-C. Integrating code generated with J2ObjC with an existing Objective-C project is actually painless, and the close correspondence between the original Java class structure and the resulting Objective-C class structure makes it easy to use the APIs from Objective-C.

J2ObjC Application ArchitectureFigure 11. J2ObjC application architecture

A key differentiator between J2ObjC and the other solutions is its preference for reference counting over garbage collection (that is, while it can use GC, it isn't supported on iOS). In addition to "transpile-time" management for reference-counting, and its support for manual reference counting and ARC via command-line flags, J2ObjC provides two mechanisms to help you deal with memory management in your Java code:

  1. Annotations to provide memory management hints (e.g. @Weak)
  2. A memory profiling tool to help detect memory cycles, called MemDebug

Garbage collection versus reference counting

While garbage collection makes our lives easier inside the Java world, it complicates them in the native world, where reference counting is the rule of the day. For instance, if you set a property of an Objective-C object to be a Java object, the garbage collector will know nothing about this reference. As a result, it may free the memory of the object if it is no longer accessible inside the Java world, even if the native world still needs it. The solution is to introduce your own form of reference counting for objects that you wish to maintain references to inside non garbage-collected structures.

ARC on iOS

Automatic reference counting (ARC) on iOS 5 and higher places the compiler in charge of counting references, rather than the developer. ARC works the same as garbage collection except that it doesn't handle cycles, for instance in cases where an object contains a reference to another object, which (transitively) contains a reference to the first object. In this case a "dead" cycle of objects would be freed when using garbage collection, but not when using ARC. The solution provided by ARC is to denote some references as "weak" references so that they don't affect the reference count for an object. This can effectively break a cycle and allow these cycles of objects to be correctly freed when they are no longer referenced. See Resources to learn more.



As an example, consider this snippet from an Objective-C application that includes some code generated by XMLVM:

@interface NotesListController
    @property JAVA_OBJECT notes;
@end

Here we are declaring a property on an Objective-C classNotesListController to be of type JAVA_OBJECT. The problem is that Objective-C classes like NotesListController are reference-counted by the Objective-C runtime, but JAVA_OBJECTvariables (the type used by XMLVM for all Java objects) are managed by XMLVM's garbage collector. Now, suppose you assign an object to aNoteListController, like so:

self.notes = ca_weblite_crossmobile_shared_Note_getNotes__();
    // calling static java method ca.weblite.crossmobile.shared.Note.getNotes()

The garbage collector has no knowledge that self.notescontains a reference to the object that was returned from theca_weblite_crossmobile_shared_Note_getNotes__() method, so, if there are no other references to that object in the heap, the garbage collector may delete it, even though theNoteListController still has a reference to it, and still needs it. When NoteListController tries to use this object later on, that action will trigger a memory access violation.

The solution alluded to above is to make sure that the heap always includes a reference to the object until it isn't needed anymore. We could do this fairly easily by creating a simple "Auto-release pool" in Java as follows:

/**
 * Class to maintain references to Java objects in the heap.
 */
public class AutoReleasePool {
    private static Map<Object,Integer> referenceCounts = new HashMap<Object,Integer>();
    
    /**
     * Increments the reference count for an object.
     */
    public static void retain(Object o){
         Integer count = referenceCounts.get(o);
         if ( count == null ){
             count = new Integer(1);
         } else {
             count = new Integer(count.intValue()+1);
         }
         referenceCounts.put(o, count);
    }
    
    /**
     * Decrements the reference count for an object.
     */
    public static void release(Object o){
        Integer count = referenceCounts.get(o);
        if ( count == null ){
            return;
        }
        
        count = new Integer(count.intValue()-1);
        if ( count.intValue() <= 0 ){
            referenceCounts.remove(o);
        } else {
            referenceCounts.put(o, count);
        }
    }
}

Using this class, we would "retain" a JAVA_OBJECT when it is set as a property of an Objective-C class as follows:

if ( self.notes != NULL ){
    AutoReleasePool_release___java_lang_Object(self.notes);
        // Release old object we don't need it anymore
}
self.notes = ca_weblite_crossmobile_shared_Note_getNotes__();
    // calling static java method ca.weblite.crossmobile.shared.Note.getNotes()
if ( self.notes != NULL ){
    AutoReleasePool_retain___java_lang_Object(self.notes);
        // Retain the new object in the heap for GC
}
FEATURED RESOURCE
Presented by Attachmate

This paper discusses both new and traditional approaches to legacy modernization, while highlighting a

LEARN MORE

Java iOS tools comparison

It is very nice to be able, once again, to write libraries in Java and deploy them everywhere. Each tool that I have discussed in this article has strengths and weaknesses. Codename One is the only Java iOS tool that currently comes close to the old "Write once, run anywhere" mantra, and it provides the most coherent development experience. I recommend checking it out if you're looking for a cross-platform environment for writing mobile apps.

If you would prefer to use Apple's native tools for your user interface, so that you can access all of Apple's cutting-edge libraries, then J2ObjC is a good option for sharing business logic.

I believe that XMLVM is among the most brilliant software development inventions of the past decade. Starting out as an academic research project that served as a proof of concept, it has enormous potential for bridging gaps between different platforms, and many of its most powerful uses may yet be discovered. XMLVM has already been used to successfully port apps from Android to HTML5/CSS/JavaScript and from Java to C, Objective-C, and C#. With a little bit of sweat, people-power, and ingenuity, perhaps it could be expanded into some sort of universal translator between all programming languages.

However, if your goal is simply to write Java applications and deploy them on iOS devices, XMLVM may not be the most practical tool for your needs. The save/compile/test cycle can be quite slow because the Java .class files could be converted into a couple thousand C source files that all need to be recompiled in Xcode. At its most practical, XMLVM currently serves as an engine for other tools like Codename One. (See the Codename One SVN repository for some great examples of XMLVM in action.)

RoboVM is a brand new Java-to-iOS tool that has much potential. Currently at release 0.0.1, it isn't quite ready for production as it is still missing many Cocoa bindings, and many features aren't yet implemented. However, it has a strong foundation in LLVM, and some very nice tools for interfacing with the native environment. I think it won't be long before RoboVM is ready for showtime.

Avian caters to a slightly different market than the rest of these tools. Its simple lightweight JVM makes it extremely portable to many different platforms, but its lack of Cocoa bindings and compatibility libraries makes it a less-than-ideal choice for writing Java applications for iOS. Avian could be used as the foundation for other tools that might allow developers to deploy Java onto iOS, however.

In conclusion

This article has been a brief survey of five open source tools for Java iOS development. You can learn more about the tools by visiting the Resources section and checking out examples on their individual websites. If you find that you love working with a particular tool, consider joining the developer community and contributing to making the project even better. All of the tools discussed in this article are open source, so any contribution you make will go toward building a more vibrant Java ecosystem.

Steve Hannah works as a software developer for Simon Fraser University in Vancouver, Canada, where he develops enterprise solutions using such technologies as PHP, MySQL, HTML5/CSS/JavaScript, and, of course, Java. He develops and maintains Xataface, an open source framework for building data-driven web applications, and has contributed to many other open source projects, both in documentation and code. He periodically writes about Java, mobile development, and other software related topics on his blog.

Learn more about this topic


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值