Binding Java and Web Services to Native Code
The Native Connector Architecture (NCA) is a model that allows for the automatic generation of code bridges between differing languages and platforms. Given a description of the interfaces exposed (and desired), it is then possible to derive and generate the code necessary to bridge the two bodies of code. The architecture defines an extensible and highly configurable model for the description of interfaces as well as the generation of bridging code using open standards for general use. As a result, bridges can easily be created between, for example, the C++ and JavaTM languages, differing C++ Application Binary Interfaces (ABI), Web service protocols (such as SOAP), as well as inter-platform bridges (for example, Microsoft COM/.NET to SolarisTM operating environment binaries).
At present, there are a number of models for bridging bodies of code or applications. Examples include:
Problems and Issues
The general problem of integration between languages and platforms is that for each such bridge between architectures, a new implementation must be created to provide the binding between environments. Worse, for each new application, even though the type of bridge may be identical (for example, between C++ and Java technology), specific interfaces used may be different, resulting in a brand new implementation of the bridge even though the general pattern remains the same.
In general, this manual implementation of bridging code can (and does) lead to the following issues and problems:
- Code being bridged must often be adapted to allow for the use of a different programming language or infrastructure, such as coding to a specific binary object model (COM/CORBA), porting to a specific platform, or through the use of an intermediate language, such as the C language.
- An in-depth knowledge of the platforms, languages, and sometimes an independent model for bridge code must be understood by the developer.
- Such bridges are difficult to maintain for large systems. As the number of interfaces increases, the complexity also increases, which leads to errors in initial development as well as issues with tracking and reproducing changes across an entire system.
- Because of the differing environments on each side of a piece of bridge code, required features such as runtime memory management, object lifetime management, and exception propagation must be managed somewhere within the system as well as injected into each API or set of APIs in the bridge.
The general result is sub-optimal performance of a bridged system because tuning a large-scale, complex application across multiple languages or platforms is necessarily difficult and frequently not attempted until it becomes a problem on deployment.
JNI Integration Model
As an example of such an existing technology, the JNI (Java Native Interface) is a model for integration used by the Java platform. As with all existing bridging technologies or architectures, the general rule is to pick a common implementation language or technology (for instance, a subset of the languages to be bridged) and use that as the foundation for the bridging code. Each component being bridged must therefore implement any conversions and handle any implementation-specific features on its side of the bridge. For the Java language, the C language is a natural fit as a bridging language, for a number of reasons:
- Most popular programming languages (including Java) in use today for commercial purposes are in the same language family, such as C, or have a common model for integrating with the language.
- Most operating systems and environments provide support for the use of libraries which follow C guidelines for interface binding.
The general steps one must use in a JNI-based solution are shown in Figure 1:
Figure 1: The JNI Process
JNI requires special handling within the Java code to enable, load, and use native libraries within the Java environment, namely:
- The dynamic library must be locatable, either via an absolute path or through the use of environment settings, which the dynamic loader uses to find such libraries.
- The Java application must explicitly load the dynamic library with functions provided by the JDKTM.
- The functions defined must be named appropriately so that the dynamic linker can bind calls within the Java code to the native methods.
- The implementation of the native methods must follow specific conventions and use types defined by the JNI specification.
Native Connector Architecture Concepts
NCA defines a model as a process designed to reduce or eliminate the risks and complexity involved with manual integration between languages or platforms such as represented by the Java to C++ language example. While the architecture is agnostic in terms of which languages or platforms can be integrated, in the following discussion examples will typically use the bridging of the Java and C++ languages as an example of the solutions that the architecture provides.
The underlying principles behind NCA are:
- Existing APIs and the desired API are known and can be represented as metadata.
- Tools implementing NCA, such as the Sun ONE StudioTM Native Connector Tool (part of Sun ONE Studio's enterprise class development tools) can understand the semantics of the languages or platforms being bridged.
- Integration between the interfaces, languages, and platforms can be represented by reproducible patterns.
- Applying these patterns against the metadata-based API descriptions will result in a data-driven automation process to generate code.
- A suitable runtime environment exists to manage a generated bridge.