Chapter 2
KNI Goals
A Java virtual machine commonly needs access to various native functions in order to interact with the outside world. For instance, all the low-level graphics functions, file access functions, networking functions, or other similar routines that depend on the underlying operating system services typically need to be written in native code.
The way these native functions are made available to the Java virtual machine can vary considerably from one virtual machine implementation to another. In order to minimize the work that is needed when porting the native functions, the Java Native Interface (JNI) standard was created.
In a traditional Java virtual machine implementation, the Java Native Interface serves two purposes:
- JNI serves as a common interface for virtual machine implementers so that the same native functions will work unmodified with different virtual machines.
- JNI provides Java-level APIs that make it possible for a Java programmer to dynamically load libraries and access native functions in those libraries.
Unfortunately, because of its general nature, JNI is rather expensive and introduces a significant memory and performance overhead to the way the JVM calls native functions. Also, the ability to dynamically load and call arbitrary native functions from Java programs could pose significant security problems in the absence of the full Java 2 security model.
High-level goal of the KNI. The high-level goal of the K Native Interface Specification is to define a logical subset of the Java Native Interface that is appropriate for low-power, memory-constrained devices. KNI follows the function naming conventions and other aspects of the JNI as far as this is possible and reasonable within the strict memory limits of CLDC target devices and in the absence of the full Java 2 security model. Since KNI is intended to be significantly more lightweight than JNI, some aspects of the interface, such as the parameter passing conventions, have been completely redesigned and are significantly different from JNI.
More specifically, the goals of the KNI include the following:
- Source-level portability of native code. KNI is intended to make it possible to share source code of native functions so that the same native function source code can be used in multiple virtual machines without modifications (of course, native code that is operating system specific will have to be ported from one system to another.)
- Isolation of virtual machine implementation details from the native functions. KNI is intended to isolate the native function programmer from virtual machine implementation details. When writing new native functions, the programmer is not required to know anything about garbage collection details, object layout, class data structures, include file dependencies, or any other VM-specific implementation details.
- Memory efficiency and minimal performance overhead. KNI is intended to be significantly more efficient and compact than a full JNI implementation. Unlike in JNI, no temporary data structures or “marshalling” of parameter passing is required at the implementation level.
As mentioned above, KNI is a “logical subset” of JNI that follows the JNI conventions as much as it makes sense given the strict memory constraints, but with some considerable design and implementation differences. The list below summarizes the most significant design differences between the JNI and KNI:
- KNI is an implementation-level API. KNI is an implementation-level API that is targeted primarily at VM implementers and device manufacturers who need to add new native functions to an existing J2ME virtual machine. Unlike JNI, the presence of the KNI is completely invisible to the Java programmer.
- No binary compatibility of native code. KNI is intended to provide source-level compatibility of native code. Unlike JNI, KNI does not guarantee that binary libraries containing native code could be linked into different virtual machines without recompilation.
- No support for dynamically loaded native libraries. KNI does not provide any mechanisms for dynamically loading native libraries into the virtual machine. Hence, any new functionality added via the native function mechanism must be done by modifying the VM native function tables and rebuilding from source. This is compliant with the security requirements imposed by the CLDC Specification.
- No Java-level access to arbitrary native functions. Unlike JNI, KNI provides no Java-level APIs to invoke other native functions than those that have been pre-built into the Java virtual machine implementation. This is compliant with the security requirements imposed by the CLDC Specification.
- No class creation, object instantiation or Java method calling from native functions. To greatly simplify the implementation of the native interface and to keep the implementation small and less error-prone, KNI does not provide any mechanisms for creating new Java classes, instantiating objects (other than strings), or calling Java methods from native code. When creating new objects that need to be manipulated in native code, the necessary objects must be created at the Java level and passed to native code as parameters.
- Parameter passing conventions are different from JNI. To reduce implementation overhead, the parameter passing conventions of KNI are significantly different from JNI. KNI uses a “register-based” approach in which arguments can be read directly from the stack frame in an implementation-independent fashion. Unlike in the old KVM native interface, no explicit pushing or popping of parameters is required or allowed.
|
KNI Specification K Native Interface (KNI), 1.0
|
Copyright ©
2002 Sun Microsystems, Inc. All rights reserved.