6.2.2 Java binding

Sony Ericsson’s Java environment allows independently developed applications and games to run on its cellular phones. This environment supports the Connected Limited Device Configuration (CLDC) of the Micro Edition of Java, as well as its Mobile Information Device Profile (MIDP). Sony Ericsson also supports a large number of supplemental specifications, in the form of Java Standardization Requests (JSRs).

In addition to allowing users to add software to their own devices, the Java environment allows Sony Ericsson itself to develop applications and related functionality in Java. Having a standardized application platform also makes it possible to outsource development to other development organizations. At the 2009 JavaOne conference, Sony Ericsson stated that all internal application development will be done in Java in the future (Sun Microsystems 2009).

In order to support internal Java development, there must be a way to access native functionality that goes beyond that offered by the vendor-neutral Java interfaces. A Java binding for ECMX exists for this purpose, which is not only used by Sony Ericsson’s applications, but also by some of the company’s JSR implementations.

All Java applications in Sony Ericsson’s system run in a specialized process, which can run multiple applications simultaneously (it includes an internal scheduler that ensures that Java applications get an equal share of the host’s resources). The Java binding enables Java applications to access native services that offer IDL interfaces. Java applications can pass outgoing interface references to operations of native objects, and can thus be notified when events occur, or request information from native objects asynchronously (as well as synchronously). Aside from calling Java objects through outgoing interfaces, native code cannot call on the services of Java objects—all interactions between native and Java code must thus be initiated from Java. Also, while native code can execute in the Java process, Java code always executes in the Java process.

The IDL compiler strives to create Java code that fits in with its environment. RVoid return values that signal errors give rise to exceptions, output arguments are mapped to true return values1 and ECMX types are mapped to the most appropriate Java type—ECMX interfaces are mapped to Java interfaces and pointers to characters are mapped to Java String objects, for instance. Java developers need not concern themselves with the IShell interface—ECMX objects are instantiated using static methods of generated Java classes that correspond to ECMX classes (there is one static factory method per interface implemented by an ECMX class). Nor do Java developers need to handle reference counting—the system automatically adds a reference to the native object when the Java object representing it is created, and removes it when the Java object is collected by the garbage collector.

Native ECMX objects are represented by Java proxy objects, which implement the generated Java interfaces that correspond to IDL interfaces. A Java proxy object maintains its link to the native object by including its address as part of its instance data. A simple way to enable these proxy objects to call on the services of the native ECMX objects would be to mark the Java methods corresponding to ECMX operations as native, and generate C code performing the call at build-time.

Presumably for reasons of space-efficiency, Sony Ericsson instead opts to handle all such calls with a single native function (that is part of the ECMX runtime system). The Java proxy objects package all arguments in a format easily digestible by this function, which converts them to the format expected by native objects (using the foreign function interface of the Java virtual machine). As the native function does not have compile-time knowledge of the call to invoke, it must invoke the call using code that is call-agnostic, which is not possible in C. Hence, this part is written in architecture-specific assembly code, which manually pushes a stack frame containing the arguments onto the call stack, and jumps to the implementation of the native operation. If the native object executes in the client’s context, control is passed directly to the native object, executing in the Java process. If the native object runs in a different process, the object that control is passed to is a client-side proxy object that forwards the call to a server-side proxy object.

Enabling Java code to be called from native code is straight-forward, as Java code always runs in the Java process. Had it been possible to run Java code in the caller’s native process, outside of the Java process, an ECMX object would have had to be synthesized at runtime, with an implementation forwarding all calls to Java using the foreign function interface of the Java virtual machine (as suggested in section 5.4.1). As Java code is restricted to the Java process, all Java calls from native processes are realized using inter-process communication. The native process invokes operations on a native ECMX object, a client-side proxy, which sends messages to the Java process.

The Java process runs its own message loop and can, with the help of the ECMX runtime system, route messages directly to Java objects—handlers—that have previously expressed an interest in handling certain messages. The server-side proxy that receives messages sent by a native client-side proxy is thus written in Java, and marshals arguments with the help of native functions in the ECMX runtime system, after which it invokes the call on the target Java object. The ability of the Java process message loop to forward messages directly to handlers is analogous to what the OPA message loop does for native processes.

Footnotes

  1. Multiple output arguments are permissible in the IDL dialect used by ECMX but pose problems for the Java binding (though they are supported). As a result, Sony Ericsson’s IDL guidelines warn against this construct.