JNI: Difference between revisions

From miki
Jump to navigation Jump to search
 
No edit summary
Line 1: Line 1:
This page is over '''JNI''', The ''Java Native Interface''.
This page is over '''JNI''', The ''Java Native Interface'' of the java language. For other features, see the [[Java]] page.


== References ==
* Sheng Liang, <u>The Java Native Interace &mdash; Programmer's Guide and Specification</u>, Addison Wesley<ref name="Liang">Sheng Liang, <u>The Java Native Interace &mdash; Programmer's Guide and Specification</u>, Addison Wesley</ref>.
== Frequent Caveats ==
== Frequent Caveats ==
From <ref name="Liang"/>:
References:
* Sheng Liang, <u>The Java Native Interace &mdash; Programmer's Guide and Specification</u>, Addison Wesley.



; Don't cache <tt>JNIEnv</tt> between threads
; Don't cache <tt>JNIEnv</tt> between threads
Line 16: Line 16:
; Cache ''field / Method ID'' at the time class is created
; Cache ''field / Method ID'' at the time class is created
: Better performance, and avoid using the wrong field/method if a sub-class that overrides some field/method is passed.
: Better performance, and avoid using the wrong field/method if a sub-class that overrides some field/method is passed.

; Use a same <tt>JNIEnv</tt> reference in different threads
:A <tt>JNIEnv</tt> pointer is only valid in the thread associated with it. Don't pass this pointer from one thread to another, or cache and use it in multiple threads.

; Pass local references to different threads
:Local referneces are valid only in the thread that created them. Instead convert local references to global reference whenever there is a possibility that multiple threads may use the same reference.

== JNI and Threads ==
=== Obtain the <code>JNIEnv</code> Pointer ===
Obtaining a reference to <code>JNIEnv</code> is necessary in order to issue JNI function calls.

For native methods called from the JVM, this is easy since the the <code>JNIEnv</code> reference for the current thread is always passed as a parameter to the call.

In other circumstance, one must first call <code>AttachCurrentThread</code> to associate the current thread to an existing JVM. If the current native thread is not yet associated, <code>AttachCurrentThead</code> will create a new <code>java.long.instance</code> in the JVM, and returns the corresponding <code>JNIEnv</code> reference. Attached thread can then issue JNI function calls. Use <code>DetachCurrentThread</code> if the current thread does not need to make native calls anymore (doing so will enable clean-up and freeing resources).

=== Registering Native Methods ===
A given JNI method declared in java must be associated to a native method implementation before it is possible to call that method. This is the purpose of the native method registration.

The standard method is to rely on the standard java 2-step mechanism:
* <code>System.loadLibrary</code> to locate and load a named native library.
* The VM locates the native method implementation in one of the loaded native libraries (e.g. <code>Foo.g()</code> requires locating and linking the native method <code>Java_Foo_g</code>

Another method is to do the association manually:

<source lang="c">
void JNICALL g_impl(JNIEnv *env, jobject self);

//...

JNINativeMethod nm;
nm.name = "g";
/* method descriptor assigned to signature field */
nm.signature = "()V";
nm.fmPtr = g_impl;
(*env)->RegisterNatives(env, cls, &nm, 1);
</source>

The advantage of the manual method:
* The standard method is slow (lazy).
* The manual method allow to update the native method implementation at runtime.
* If the VM is launched by a native application, <code>RegisterNatives</code> allows to register native methods of that application, whereas the standard method only search native implementation in native libraries, not in the application itself.

== Notes ==
<references/>

Revision as of 14:56, 24 September 2011

This page is over JNI, The Java Native Interface of the java language. For other features, see the Java page.

References

  • Sheng Liang, The Java Native Interace — Programmer's Guide and Specification, Addison Wesley[1].

Frequent Caveats

From [1]:

Don't cache JNIEnv between threads
Each thread gets its own value of JNIEnv
Don't truncate jboolean arguments
jboolean type is actually a 8-bit type, so value like 256/512 would actually be treated like false
Don't mix thread models (green thread vs native thread) if models are different
Cache field / Method ID at the time class is created
Better performance, and avoid using the wrong field/method if a sub-class that overrides some field/method is passed.
Use a same JNIEnv reference in different threads
A JNIEnv pointer is only valid in the thread associated with it. Don't pass this pointer from one thread to another, or cache and use it in multiple threads.
Pass local references to different threads
Local referneces are valid only in the thread that created them. Instead convert local references to global reference whenever there is a possibility that multiple threads may use the same reference.

JNI and Threads

Obtain the JNIEnv Pointer

Obtaining a reference to JNIEnv is necessary in order to issue JNI function calls.

For native methods called from the JVM, this is easy since the the JNIEnv reference for the current thread is always passed as a parameter to the call.

In other circumstance, one must first call AttachCurrentThread to associate the current thread to an existing JVM. If the current native thread is not yet associated, AttachCurrentThead will create a new java.long.instance in the JVM, and returns the corresponding JNIEnv reference. Attached thread can then issue JNI function calls. Use DetachCurrentThread if the current thread does not need to make native calls anymore (doing so will enable clean-up and freeing resources).

Registering Native Methods

A given JNI method declared in java must be associated to a native method implementation before it is possible to call that method. This is the purpose of the native method registration.

The standard method is to rely on the standard java 2-step mechanism:

  • System.loadLibrary to locate and load a named native library.
  • The VM locates the native method implementation in one of the loaded native libraries (e.g. Foo.g() requires locating and linking the native method Java_Foo_g

Another method is to do the association manually:

void JNICALL g_impl(JNIEnv *env, jobject self);

//...

JNINativeMethod nm;
nm.name = "g";
/* method descriptor assigned to signature field */
nm.signature = "()V";
nm.fmPtr = g_impl;
(*env)->RegisterNatives(env, cls, &nm, 1);

The advantage of the manual method:

  • The standard method is slow (lazy).
  • The manual method allow to update the native method implementation at runtime.
  • If the VM is launched by a native application, RegisterNatives allows to register native methods of that application, whereas the standard method only search native implementation in native libraries, not in the application itself.

Notes

  1. 1.0 1.1 Sheng Liang, The Java Native Interace — Programmer's Guide and Specification, Addison Wesley