Jump to content

Java Native Interface

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by 122.161.49.25 (talk) at 04:33, 30 October 2021 (Objectives). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

In software design, the Java Native Interface (JNI) is a foreign function interface programming framework that enables Java code running in a Java virtual machine (JVM) to call and be called by[1] native applications (programs specific to a hardware and operating system platform) and libraries written in other languages such as C, C++ and assembly.

Objectives

The JNI framework lets a native method use Java objects in the same way that Java code uses these objects. A native method can create Java objects and then inspect and use these objects to perform its tasks. A native method can also inspect and use objects created by Java application code.

Only applications and signed applets can invoke JNI.

An application that relies on JNI loses the platform portability Java offers (a partial workaround is to write a separate implementation of JNI code for each platform and have Java detect the operating system and load the correct one at runtime).

Not only can native code interface with Java, it can also draw on a Java Canvas, which is possible with the Java AWT Native Interface. The process is almost the same, with just a few changes. The Java AWT Native Interface is only available since J2SE 1.3.

JNI also allows direct access to assembly code, without even going through a C bridge.Cite error: A <ref> tag is missing the closing </ref> (see the help page).

The JNI framework does not provide any automatic garbage collection for non-JVM memory resources allocated by code executing on the native side. Consequently, native side code (such as assembly language) assumes the responsibility for explicitly releasing any such memory resources that the native code acquires.

On Linux and Solaris platforms, if the native code registers itself as a signal handler, it could intercept signals intended for the JVM. A chain of responsibility can be used to allow native code to better inter-operate with the JVM. On Windows platforms, Structured Exception Handling (SEH) may be employed to wrap native code in SEH try/catch blocks so as to capture machine (CPU/FPU) generated software interrupts (such as NULL pointer access violations and divide-by-zero operations), and to handle these situations before the interrupt is propagated back up into the JVM (i.e. Java side code), in all likelihood resulting in an unhandled exception.[original research?]

The encoding used for the NewStringUTF, GetStringUTFLength, GetStringUTFChars, ReleaseStringUTFChars and GetStringUTFRegion functions is "modified UTF-8",[2] which is not valid UTF-8 for all inputs, but a different encoding really. The null character (U+0000) and codepoints not on the Basic Multilingual Plane (greater than or equal to U+10000, i.e. those represented as surrogate pairs in UTF-16) are encoded differently in modified UTF-8. Many programs actually use these functions incorrectly and treat the UTF-8 strings returned or passed into the functions as standard UTF-8 strings instead of modified UTF-8 strings. Programs should use the NewString, GetStringLength, GetStringChars, ReleaseStringChars, GetStringRegion, GetStringCritical and ReleaseStringCritical functions, which use UTF-16LE encoding on little-endian architectures and UTF-16BE on big-endian architectures, and then use a UTF-16 to UTF-8 conversion routine.[original research?]

Mapping types

The following table shows the mapping of types between Java (JNI) and native code.

C Type Java Language Type Description Type signature
unsigned char
uint8_t
jboolean unsigned 8 bits Z
signed char
int8_t
jbyte signed 8 bits B
unsigned short
uint16_t
jchar unsigned 16 bits C
short
int16_t
jshort signed 16 bits S
int
int32_t
jint signed 32 bits I

long long
int64_t

jlong signed 64 bits J
float jfloat 32 bits F
double jdouble 64 bits D
void V

In addition, the signature "L fully-qualified-class ;" would mean the class uniquely specified by that name; e.g., the signature "Ljava/lang/String;" refers to the class java.lang.String. Also, prefixing [ to the signature makes the array of that type; for example, [I means the int array type. Finally, a void signature uses the V code.

These types are interchangeable. One can use jint where you normally use an int, and vice versa, without any typecasting required. However, mapping between Java Strings and arrays to native strings and arrays is different. If a jstring is used where a char * would be, the code could crash the JVM.[original research?]

Performance

JNI incurs considerable overhead and performance loss under certain circumstances:[3]

  • Function calls to JNI methods are expensive, especially when calling a method repeatedly.
  • Native methods are not inlined by the JVM, nor can the method be JIT compiled, as the method is already compiled.
  • A Java array may be copied for access in native code, and later copied back. The cost can be linear in the size of the array.
  • If the method is passed an object, or needs to make a callback, then the native method will likely be making its own calls to the JVM. Accessing Java fields, methods and types from the native code requires something similar to reflection. Signatures are specified in strings and queried from the JVM. This is both slow and error-prone.
  • Java Strings are objects, have length and are encoded. Accessing or creating a string may require an O(n) copy.

Alternatives

Microsoft's proprietary implementation of a Java Virtual Machine (Visual J++) had a similar mechanism for calling native code from Java, called the Raw Native Interface (RNI). In addition, it had an easy way to call existing native code that wasn't itself aware of Java, such as (but not limited to) the Windows API, called J/Direct. However, following the Sun–Microsoft litigation about this implementation, Visual J++ is no longer maintained.

RNI was less clumsy to use than JNI, because no bookkeeping with a Java environment pointer was needed. Instead, all Java objects could be accessed directly. To facilitate this, a tool was used that generated header files from Java classes. Similarly, J/Direct was easier to use than using the necessary intermediate native library and JNI.

Java Native Access (JNA) is a community-developed library that provides Java programs easy access to native shared libraries without using JNI.

See also

References

  1. ^ "Java Native Interface Overview". The Java Native Interface Programmer's Guide and Specification. Retrieved 2018-12-27.
  2. ^ "JNI Types and Data Structures".
  3. ^ "java — What makes JNI calls slow? - Stack Overflow".

Bibliography