Contents | Previous | Next Java Native Interface Specification

Introduction


Chapter   1

This chapter introduces the Java Native Interface (JNI). The JNI is a native programming interface. It allows Java code that runs inside a Java Virtual Machine (VM) to interoperate with applications and libraries written in other programming languages, such as C, C++, and assembly.

The most important benefit of the JNI is that it imposes no restrictions on the implementation of the underlying Java VM. Therefore, Java VM vendors can add support for the JNI without affecting other parts of the VM. Programmers can write one version of a native application or library and expect it to work with all Java VMs supporting the JNI.

This chapter covers the following topics:

Java Native Interface Overview

While you can write applications entirely in Java, there are situations where Java alone does not meet the needs of your application. Programmers use the JNI to write Java native methods to handle those situations when an application cannot be written entirely in Java.

The following examples illustrate when you need to use Java native methods:

By programming through the JNI, you can use native methods to:

You can also use the JNI with the Invocation API to enable an arbitrary native application to embed the Java VM. This allows programmers to easily make their existing applications Java-enabled without having to link with the VM source code.

Background

Currently, VMs from different vendors offer different native method interfaces. These different interfaces force programmers to produce, maintain, and distribute multiple versions of native method libraries on a given platform.

We briefly examine some of the existing native method interfaces, such as:

JDK 1.0 Native Method Interface

JDK 1.0 shipped with a native method interface. Unfortunately, there are two major reasons that this interface is unsuitable for adoption by other Java VMs.

First, the native code accesses fields in Java objects as members of C structures. However, the Java Language Specification does not define how objects are laid out in memory. If a Java VM lays out objects differently in memory, then the programmer would have to recompile the native method libraries.

Second, JDK 1.0’s native method interface relies on a conservative garbage collector. The unrestricted use of the unhand macro, for example, makes it necessary to conservatively scan the native stack.

Java Runtime Interface

Netscape proposed the Java Runtime Interface (JRI), a general interface for services provided in the Java virtual machine. JRI is designed with portability in mind---it makes few assumptions about the implementation details in the underlying Java VM. The JRI addresses a wide range of issues, including native methods, debugging, reflection, embedding (invocation), and so on.

Raw Native Interface and Java/COM Interface

The Microsoft Java VM supports two native method interfaces. At the low level, it provides an efficient Raw Native Interface (RNI). The RNI offers a high degree of source-level backward compatibility with the JDK’s native method interface, although it has one major difference. Instead of relying on conservative garbage collection, the native code must use RNI functions to interact explicitly with the garbage collector.

At a higher level, Microsoft's Java/COM interface offers a language-independent standard binary interface to the Java VM. Java code can use a COM object as if it were a Java object. A Java class can also be exposed to the rest of the system as a COM class.

Objectives

We believe that a uniform, well-thought-out standard interface offers the following benefits for everyone:

The best way to achieve a standard native method interface is to involve all parties with an interest in Java VMs. Therefore we organized a series of discussions among the Java licensees on the design of a uniform native method interface. It is clear from the discussions that the standard native method interface must satisfy the following requirements:

Java Native Interface Approach

We hoped to adopt one of the existing approaches as the standard interface, because this would have imposed the least burden on programmers who had to learn multiple interfaces in different VMs. Unfortunately, no existing solutions are completely satisfactory in achieving our goals.

Netscape’s JRI is the closest to what we envision as a portable native method interface, and was used as the starting point of our design. Readers familiar with the JRI will notice the similarities in the API naming convention, the use of method and field IDs, the use of local and global references, and so on. Despite our best efforts, however, the JNI is not binary-compatible with the JRI, although a VM can support both the JRI and the JNI.

Microsoft’s RNI is an improvement over JDK 1.0 because it solves the problem of native methods working with a nonconservative garbage collector. The RNI, however, is not suitable as a VM-independent native method interface. Like the JDK, RNI native methods access Java objects as C structures. This leads to two problems:

As a binary standard, COM ensures complete binary compatibility across different VMs. Invoking a COM method requires only an indirect call, which carries little overhead. In addition, COM objects are a great improvement over dynamic-link libraries in solving versioning problems.

The use of COM as the standard Java native method interface, however, is hampered by a few factors:

Although we do not expose Java objects to the native code as COM objects, the JNI interface itself is binary-compatible with COM. We use the same jump table structure and calling convention that COM does. This means that, as soon as cross-platform support for COM is available, the JNI can become a COM interface to the Java VM.

We do not believe that the JNI should be the only native method interface supported by a given Java VM. A standard interface benefits programmers who would like to load their native code libraries into different Java VMs. In some cases, the programmer may have to use a lower-level, VM-specific interface to achieve top efficiency. In other cases, the programmer might use a higher-level interface to build software components. Indeed, we hope that, as the Java environment and component software technologies become more mature, native methods will gradually lose their significance.

Programming to the JNI

Native method programmers should start programming to the JNI. Programming to the JNI insulates you from unknowns, such as the vendor’s VM that the end user might be running. By conforming to the JNI standard, you will give a native library the best chance to run in a given Java VM. For example, although JDK 1.1 will continue to support the old-style native method interface that was implemented in JDK 1.0, it is certain that future versions of the JDK will stop supporting the old-style native method interface. Native methods relying on the old-style interface will have to be rewritten.

If you are implementing a Java VM, you should implement the JNI. We (Javasoft and the licensees) have tried our best to ensure that the JNI does not impose any overhead or restrictions on your VM implementation, including object representation, garbage collection scheme, and so on. Please let us know if you run into any problems we might have overlooked.

Changes in JDK 1.1.2

To better support the Java Runtime Environment (JRE), the Invocation API has been extended in JDK 1.1.2 in a few minor ways. The changes do not break any existing code. The JNI Native Method Interface has not been changed.

 


Contents | Previous | Next