blob: 9f880ec557a08fa3310d6619aba649de6e02a64e [file] [log] [blame]
Elliott Hughes10c7ceb2011-04-13 19:01:11 -07001page.title=JNI Tips
Scott Main1c2dea02013-04-10 18:59:29 -07002page.tags="ndk","native"
3
Dirk Doughertyd5894212012-11-28 18:53:10 -08004page.article=true
Elliott Hughes10c7ceb2011-04-13 19:01:11 -07005@jd:body
6
Scott Main22cc2762012-11-07 16:35:16 -08007<div id="tb-wrapper">
8<div id="tb">
Elliott Hughes10c7ceb2011-04-13 19:01:11 -07009
10<h2>In this document</h2>
Scott Maina3f0e012013-09-19 17:45:40 -070011<ol class="nolist">
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070012 <li><a href="#JavaVM_and_JNIEnv">JavaVM and JNIEnv</a></li>
13 <li><a href="#threads">Threads</a></li>
14 <li><a href="#jclass_jmethodID_and_jfieldID">jclass, jmethodID, and jfieldID</a></li>
15 <li><a href="#local_and_global_references">Local and Global References</a></li>
16 <li><a href="#UTF_8_and_UTF_16_strings">UTF-8 and UTF-16 Strings</a></li>
17 <li><a href="#arrays">Primitive Arrays</a></li>
18 <li><a href="#region_calls">Region Calls</a></li>
19 <li><a href="#exceptions">Exceptions</a></li>
20 <li><a href="#extended_checking">Extended Checking</a> </li>
21 <li><a href="#native_libraries">Native Libraries</a></li>
22 <li><a href="#64_bit">64-bit Considerations</a></li>
Elliott Hughes1890b872011-12-16 13:59:54 -080023 <li><a href="#unsupported">Unsupported Features/Backwards Compatibility</a></li>
Elliott Hughes43873352011-07-20 15:02:35 -070024 <li><a href="#faq_ULE">FAQ: Why do I get <code>UnsatisfiedLinkError</code></a></li>
25 <li><a href="#faq_FindClass">FAQ: Why didn't <code>FindClass</code> find my class?</a></li>
26 <li><a href="#faq_sharing">FAQ: How do I share raw data with native code?</a></li>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070027</ol>
28
29</div>
30</div>
31
Elliott Hughes868d74e2011-09-27 16:27:31 -070032<p>JNI is the Java Native Interface. It defines a way for managed code
33(written in the Java programming language) to interact with native
34code (written in C/C++). It's vendor-neutral, has support for loading code from
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070035dynamic shared libraries, and while cumbersome at times is reasonably efficient.</p>
36
Elliott Hughes84303f52012-12-18 17:24:36 -080037<p>If you're not already familiar with it, read through the
38<a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html">Java Native Interface Specification</a>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070039to get a sense for how JNI works and what features are available. Some
40aspects of the interface aren't immediately obvious on
Elliott Hughes84303f52012-12-18 17:24:36 -080041first reading, so you may find the next few sections handy.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070042
43
44<a name="JavaVM_and_JNIEnv" id="JavaVM_and_JNIEnv"></a>
45<h2>JavaVM and JNIEnv</h2>
46
47<p>JNI defines two key data structures, "JavaVM" and "JNIEnv". Both of these are essentially
Elliott Hughesf2433432011-04-13 19:01:11 -070048pointers to pointers to function tables. (In the C++ version, they're classes with a
49pointer to a function table and a member function for each JNI function that indirects through
50the table.) The JavaVM provides the "invocation interface" functions,
Elliott Hughes868d74e2011-09-27 16:27:31 -070051which allow you to create and destroy a JavaVM. In theory you can have multiple JavaVMs per process,
52but Android only allows one.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070053
54<p>The JNIEnv provides most of the JNI functions. Your native functions all receive a JNIEnv as
55the first argument.</p>
56
Elliott Hughes868d74e2011-09-27 16:27:31 -070057<p>The JNIEnv is used for thread-local storage. For this reason, <strong>you cannot share a JNIEnv between threads</strong>.
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070058If a piece of code has no other way to get its JNIEnv, you should share
Elliott Hughes43873352011-07-20 15:02:35 -070059the JavaVM, and use <code>GetEnv</code> to discover the thread's JNIEnv. (Assuming it has one; see <code>AttachCurrentThread</code> below.)</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070060
61<p>The C declarations of JNIEnv and JavaVM are different from the C++
Elliott Hughes43873352011-07-20 15:02:35 -070062declarations. The <code>"jni.h"</code> include file provides different typedefs
63depending on whether it's included into C or C++. For this reason it's a bad idea to
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070064include JNIEnv arguments in header files included by both languages. (Put another way: if your
Elliott Hughes43873352011-07-20 15:02:35 -070065header file requires <code>#ifdef __cplusplus</code>, you may have to do some extra work if anything in
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070066that header refers to JNIEnv.)</p>
67
68<a name="threads" id="threads"></a>
69<h2>Threads</h2>
70
Elliott Hughes868d74e2011-09-27 16:27:31 -070071<p>All threads are Linux threads, scheduled by the kernel. They're usually
72started from managed code (using <code>Thread.start</code>),
73but they can also be created elsewhere and then attached to the JavaVM. For
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070074example, a thread started with <code>pthread_create</code> can be attached
75with the JNI <code>AttachCurrentThread</code> or
76<code>AttachCurrentThreadAsDaemon</code> functions. Until a thread is
Elliott Hughes868d74e2011-09-27 16:27:31 -070077attached, it has no JNIEnv, and <strong>cannot make JNI calls</strong>.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070078
Elliott Hughes868d74e2011-09-27 16:27:31 -070079<p>Attaching a natively-created thread causes a <code>java.lang.Thread</code>
80object to be constructed and added to the "main" <code>ThreadGroup</code>,
81making it visible to the debugger. Calling <code>AttachCurrentThread</code>
82on an already-attached thread is a no-op.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070083
Elliott Hughes868d74e2011-09-27 16:27:31 -070084<p>Android does not suspend threads executing native code. If
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070085garbage collection is in progress, or the debugger has issued a suspend
Elliott Hughes868d74e2011-09-27 16:27:31 -070086request, Android will pause the thread the next time it makes a JNI call.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070087
88<p>Threads attached through JNI <strong>must call
89<code>DetachCurrentThread</code> before they exit</strong>.
Elliott Hughes43873352011-07-20 15:02:35 -070090If coding this directly is awkward, in Android 2.0 (Eclair) and higher you
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070091can use <code>pthread_key_create</code> to define a destructor
92function that will be called before the thread exits, and
93call <code>DetachCurrentThread</code> from there. (Use that
94key with <code>pthread_setspecific</code> to store the JNIEnv in
95thread-local-storage; that way it'll be passed into your destructor as
96the argument.)</p>
97
Elliott Hughesf2433432011-04-13 19:01:11 -070098
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070099<a name="jclass_jmethodID_and_jfieldID" id="jclass_jmethodID_and_jfieldID"></a>
100<h2>jclass, jmethodID, and jfieldID</h2>
101
102<p>If you want to access an object's field from native code, you would do the following:</p>
103
104<ul>
105<li> Get the class object reference for the class with <code>FindClass</code></li>
106<li> Get the field ID for the field with <code>GetFieldID</code></li>
Elliott Hughes43873352011-07-20 15:02:35 -0700107<li> Get the contents of the field with something appropriate, such as
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700108<code>GetIntField</code></li>
109</ul>
110
111<p>Similarly, to call a method, you'd first get a class object reference and then a method ID. The IDs are often just
Elliott Hughes868d74e2011-09-27 16:27:31 -0700112pointers to internal runtime data structures. Looking them up may require several string
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700113comparisons, but once you have them the actual call to get the field or invoke the method
114is very quick.</p>
115
116<p>If performance is important, it's useful to look the values up once and cache the results
Elliott Hughes868d74e2011-09-27 16:27:31 -0700117in your native code. Because there is a limit of one JavaVM per process, it's reasonable
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700118to store this data in a static local structure.</p>
119
120<p>The class references, field IDs, and method IDs are guaranteed valid until the class is unloaded. Classes
121are only unloaded if all classes associated with a ClassLoader can be garbage collected,
Elliott Hughes43873352011-07-20 15:02:35 -0700122which is rare but will not be impossible in Android. Note however that
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700123the <code>jclass</code>
124is a class reference and <strong>must be protected</strong> with a call
125to <code>NewGlobalRef</code> (see the next section).</p>
126
127<p>If you would like to cache the IDs when a class is loaded, and automatically re-cache them
128if the class is ever unloaded and reloaded, the correct way to initialize
129the IDs is to add a piece of code that looks like this to the appropriate class:</p>
130
131<pre> /*
132 * We use a class initializer to allow the native code to cache some
Elliott Hughes43873352011-07-20 15:02:35 -0700133 * field offsets. This native function looks up and caches interesting
134 * class/field/method IDs. Throws on failure.
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700135 */
Elliott Hughes43873352011-07-20 15:02:35 -0700136 private static native void nativeInit();
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700137
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700138 static {
Elliott Hughes43873352011-07-20 15:02:35 -0700139 nativeInit();
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700140 }</pre>
Elliott Hughesf2433432011-04-13 19:01:11 -0700141
Elliott Hughes43873352011-07-20 15:02:35 -0700142<p>Create a <code>nativeClassInit</code> method in your C/C++ code that performs the ID lookups. The code
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700143will be executed once, when the class is initialized. If the class is ever unloaded and
Elliott Hughes43873352011-07-20 15:02:35 -0700144then reloaded, it will be executed again.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700145
146<a name="local_and_global_references" id="local_and_global_references"></a>
147<h2>Local and Global References</h2>
148
Elliott Hughes868d74e2011-09-27 16:27:31 -0700149<p>Every argument passed to a native method, and almost every object returned
150by a JNI function is a "local reference". This means that it's valid for the
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700151duration of the current native method in the current thread.
Elliott Hughes868d74e2011-09-27 16:27:31 -0700152<strong>Even if the object itself continues to live on after the native method
153returns, the reference is not valid.</strong>
154<p>This applies to all sub-classes of <code>jobject</code>, including
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700155<code>jclass</code>, <code>jstring</code>, and <code>jarray</code>.
Elliott Hughes868d74e2011-09-27 16:27:31 -0700156(The runtime will warn you about most reference mis-uses when extended JNI
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700157checks are enabled.)</p>
Elliott Hughes868d74e2011-09-27 16:27:31 -0700158<p>The only way to get non-local references is via the functions
159<code>NewGlobalRef</code> and <code>NewWeakGlobalRef</code>.
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700160
161<p>If you want to hold on to a reference for a longer period, you must use
162a "global" reference. The <code>NewGlobalRef</code> function takes the
163local reference as an argument and returns a global one.
164The global reference is guaranteed to be valid until you call
165<code>DeleteGlobalRef</code>.</p>
166
Elliott Hughes868d74e2011-09-27 16:27:31 -0700167<p>This pattern is commonly used when caching a jclass returned
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700168from <code>FindClass</code>, e.g.:</p>
Elliott Hughes13bac602011-07-19 12:05:04 -0700169<pre>jclass localClass = env-&gt;FindClass("MyClass");
170jclass globalClass = reinterpret_cast&lt;jclass&gt;(env-&gt;NewGlobalRef(localClass));</pre>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700171
172<p>All JNI methods accept both local and global references as arguments.
Elliott Hughes43873352011-07-20 15:02:35 -0700173It's possible for references to the same object to have different values.
174For example, the return values from consecutive calls to
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700175<code>NewGlobalRef</code> on the same object may be different.
176<strong>To see if two references refer to the same object,
177you must use the <code>IsSameObject</code> function.</strong> Never compare
Elliott Hughes43873352011-07-20 15:02:35 -0700178references with <code>==</code> in native code.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700179
180<p>One consequence of this is that you
181<strong>must not assume object references are constant or unique</strong>
182in native code. The 32-bit value representing an object may be different
183from one invocation of a method to the next, and it's possible that two
184different objects could have the same 32-bit value on consecutive calls. Do
185not use <code>jobject</code> values as keys.</p>
186
187<p>Programmers are required to "not excessively allocate" local references. In practical terms this means
188that if you're creating large numbers of local references, perhaps while running through an array of
Elliott Hughes868d74e2011-09-27 16:27:31 -0700189objects, you should free them manually with
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700190<code>DeleteLocalRef</code> instead of letting JNI do it for you. The
Elliott Hughes868d74e2011-09-27 16:27:31 -0700191implementation is only required to reserve slots for
Elliott Hughes10c7ceb2011-04-13 19:01:11 -070019216 local references, so if you need more than that you should either delete as you go or use
Elliott Hughes868d74e2011-09-27 16:27:31 -0700193<code>EnsureLocalCapacity</code>/<code>PushLocalFrame</code> to reserve more.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700194
Elliott Hughes868d74e2011-09-27 16:27:31 -0700195<p>Note that <code>jfieldID</code>s and <code>jmethodID</code>s are opaque
196types, not object references, and should not be passed to
197<code>NewGlobalRef</code>. The raw data
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700198pointers returned by functions like <code>GetStringUTFChars</code>
Elliott Hughes868d74e2011-09-27 16:27:31 -0700199and <code>GetByteArrayElements</code> are also not objects. (They may be passed
200between threads, and are valid until the matching Release call.)</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700201
202<p>One unusual case deserves separate mention. If you attach a native
Elliott Hughes868d74e2011-09-27 16:27:31 -0700203thread with <code>AttachCurrentThread</code>, the code you are running will
204never automatically free local references until the thread detaches. Any local
205references you create will have to be deleted manually. In general, any native
206code that creates local references in a loop probably needs to do some manual
207deletion.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700208
209<a name="UTF_8_and_UTF_16_strings" id="UTF_8_and_UTF_16_strings"></a>
210<h2>UTF-8 and UTF-16 Strings</h2>
211
Elliott Hughes13bac602011-07-19 12:05:04 -0700212<p>The Java programming language uses UTF-16. For convenience, JNI provides methods that work with <a href="http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8">Modified UTF-8</a> as well. The
213modified encoding is useful for C code because it encodes \u0000 as 0xc0 0x80 instead of 0x00.
214The nice thing about this is that you can count on having C-style zero-terminated strings,
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700215suitable for use with standard libc string functions. The down side is that you cannot pass
Elliott Hughes868d74e2011-09-27 16:27:31 -0700216arbitrary UTF-8 data to JNI and expect it to work correctly.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700217
Elliott Hughes868d74e2011-09-27 16:27:31 -0700218<p>If possible, it's usually faster to operate with UTF-16 strings. Android
219currently does not require a copy in <code>GetStringChars</code>, whereas
220<code>GetStringUTFChars</code> requires an allocation and a conversion to
221UTF-8. Note that
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700222<strong>UTF-16 strings are not zero-terminated</strong>, and \u0000 is allowed,
223so you need to hang on to the string length as well as
Elliott Hughes868d74e2011-09-27 16:27:31 -0700224the jchar pointer.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700225
Elliott Hughes43873352011-07-20 15:02:35 -0700226<p><strong>Don't forget to <code>Release</code> the strings you <code>Get</code></strong>. The
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700227string functions return <code>jchar*</code> or <code>jbyte*</code>, which
228are C-style pointers to primitive data rather than local references. They
Elliott Hughes43873352011-07-20 15:02:35 -0700229are guaranteed valid until <code>Release</code> is called, which means they are not
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700230released when the native method returns.</p>
231
Elliott Hughes13bac602011-07-19 12:05:04 -0700232<p><strong>Data passed to NewStringUTF must be in Modified UTF-8 format</strong>. A
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700233common mistake is reading character data from a file or network stream
234and handing it to <code>NewStringUTF</code> without filtering it.
235Unless you know the data is 7-bit ASCII, you need to strip out high-ASCII
Elliott Hughes13bac602011-07-19 12:05:04 -0700236characters or convert them to proper Modified UTF-8 form. If you don't,
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700237the UTF-16 conversion will likely not be what you expect. The extended
238JNI checks will scan strings and warn you about invalid data, but they
239won't catch everything.</p>
240
241<a name="arrays" id="arrays"></a>
242<h2>Primitive Arrays</h2>
243
244<p>JNI provides functions for accessing the contents of array objects.
245While arrays of objects must be accessed one entry at a time, arrays of
246primitives can be read and written directly as if they were declared in C.</p>
247
248<p>To make the interface as efficient as possible without constraining
Elliott Hughes868d74e2011-09-27 16:27:31 -0700249the VM implementation, the <code>Get&lt;PrimitiveType&gt;ArrayElements</code>
250family of calls allows the runtime to either return a pointer to the actual elements, or
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700251allocate some memory and make a copy. Either way, the raw pointer returned
252is guaranteed to be valid until the corresponding <code>Release</code> call
253is issued (which implies that, if the data wasn't copied, the array object
254will be pinned down and can't be relocated as part of compacting the heap).
Elliott Hughes43873352011-07-20 15:02:35 -0700255<strong>You must <code>Release</code> every array you <code>Get</code>.</strong> Also, if the <code>Get</code>
256call fails, you must ensure that your code doesn't try to <code>Release</code> a NULL
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700257pointer later.</p>
258
259<p>You can determine whether or not the data was copied by passing in a
260non-NULL pointer for the <code>isCopy</code> argument. This is rarely
261useful.</p>
262
263<p>The <code>Release</code> call takes a <code>mode</code> argument that can
Elliott Hughes868d74e2011-09-27 16:27:31 -0700264have one of three values. The actions performed by the runtime depend upon
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700265whether it returned a pointer to the actual data or a copy of it:</p>
266
267<ul>
268 <li><code>0</code>
269 <ul>
270 <li>Actual: the array object is un-pinned.
271 <li>Copy: data is copied back. The buffer with the copy is freed.
272 </ul>
273 <li><code>JNI_COMMIT</code>
274 <ul>
275 <li>Actual: does nothing.
276 <li>Copy: data is copied back. The buffer with the copy
277 <strong>is not freed</strong>.
278 </ul>
279 <li><code>JNI_ABORT</code>
280 <ul>
281 <li>Actual: the array object is un-pinned. Earlier
282 writes are <strong>not</strong> aborted.
283 <li>Copy: the buffer with the copy is freed; any changes to it are lost.
284 </ul>
285</ul>
286
287<p>One reason for checking the <code>isCopy</code> flag is to know if
288you need to call <code>Release</code> with <code>JNI_COMMIT</code>
289after making changes to an array &mdash; if you're alternating between making
290changes and executing code that uses the contents of the array, you may be
291able to
292skip the no-op commit. Another possible reason for checking the flag is for
293efficient handling of <code>JNI_ABORT</code>. For example, you might want
294to get an array, modify it in place, pass pieces to other functions, and
295then discard the changes. If you know that JNI is making a new copy for
296you, there's no need to create another "editable" copy. If JNI is passing
297you the original, then you do need to make your own copy.</p>
298
Elliott Hughes43873352011-07-20 15:02:35 -0700299<p>It is a common mistake (repeated in example code) to assume that you can skip the <code>Release</code> call if
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700300<code>*isCopy</code> is false. This is not the case. If no copy buffer was
301allocated, then the original memory must be pinned down and can't be moved by
302the garbage collector.</p>
303
Elliott Hughes43873352011-07-20 15:02:35 -0700304<p>Also note that the <code>JNI_COMMIT</code> flag does <strong>not</strong> release the array,
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700305and you will need to call <code>Release</code> again with a different flag
306eventually.</p>
307
308
309<a name="region_calls" id="region_calls"></a>
310<h2>Region Calls</h2>
311
312<p>There is an alternative to calls like <code>Get&lt;Type&gt;ArrayElements</code>
313and <code>GetStringChars</code> that may be very helpful when all you want
314to do is copy data in or out. Consider the following:</p>
315
Elliott Hughes43873352011-07-20 15:02:35 -0700316<pre> jbyte* data = env-&gt;GetByteArrayElements(array, NULL);
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700317 if (data != NULL) {
318 memcpy(buffer, data, len);
Elliott Hughes13bac602011-07-19 12:05:04 -0700319 env-&gt;ReleaseByteArrayElements(array, data, JNI_ABORT);
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700320 }</pre>
Elliott Hughesf2433432011-04-13 19:01:11 -0700321
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700322<p>This grabs the array, copies the first <code>len</code> byte
Elliott Hughes868d74e2011-09-27 16:27:31 -0700323elements out of it, and then releases the array. Depending upon the
324implementation, the <code>Get</code> call will either pin or copy the array
325contents.
Elliott Hughes43873352011-07-20 15:02:35 -0700326The code copies the data (for perhaps a second time), then calls <code>Release</code>; in this case
327<code>JNI_ABORT</code> ensures there's no chance of a third copy.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700328
Elliott Hughes43873352011-07-20 15:02:35 -0700329<p>One can accomplish the same thing more simply:</p>
330<pre> env-&gt;GetByteArrayRegion(array, 0, len, buffer);</pre>
Elliott Hughesf2433432011-04-13 19:01:11 -0700331
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700332<p>This has several advantages:</p>
333<ul>
334 <li>Requires one JNI call instead of 2, reducing overhead.
335 <li>Doesn't require pinning or extra data copies.
336 <li>Reduces the risk of programmer error &mdash; no risk of forgetting
337 to call <code>Release</code> after something fails.
338</ul>
339
340<p>Similarly, you can use the <code>Set&lt;Type&gt;ArrayRegion</code> call
341to copy data into an array, and <code>GetStringRegion</code> or
342<code>GetStringUTFRegion</code> to copy characters out of a
343<code>String</code>.
344
345
346<a name="exceptions" id="exceptions"></a>
Elliott Hughes868d74e2011-09-27 16:27:31 -0700347<h2>Exceptions</h2>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700348
Elliott Hughes43873352011-07-20 15:02:35 -0700349<p><strong>You must not call most JNI functions while an exception is pending.</strong>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700350Your code is expected to notice the exception (via the function's return value,
Elliott Hughes43873352011-07-20 15:02:35 -0700351<code>ExceptionCheck</code>, or <code>ExceptionOccurred</code>) and return,
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700352or clear the exception and handle it.</p>
353
354<p>The only JNI functions that you are allowed to call while an exception is
355pending are:</p>
356<ul>
Elliott Hughes43873352011-07-20 15:02:35 -0700357 <li><code>DeleteGlobalRef</code>
358 <li><code>DeleteLocalRef</code>
359 <li><code>DeleteWeakGlobalRef</code>
360 <li><code>ExceptionCheck</code>
361 <li><code>ExceptionClear</code>
362 <li><code>ExceptionDescribe</code>
363 <li><code>ExceptionOccurred</code>
364 <li><code>MonitorExit</code>
365 <li><code>PopLocalFrame</code>
366 <li><code>PushLocalFrame</code>
367 <li><code>Release&lt;PrimitiveType&gt;ArrayElements</code>
368 <li><code>ReleasePrimitiveArrayCritical</code>
369 <li><code>ReleaseStringChars</code>
370 <li><code>ReleaseStringCritical</code>
371 <li><code>ReleaseStringUTFChars</code>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700372</ul>
373
374<p>Many JNI calls can throw an exception, but often provide a simpler way
375of checking for failure. For example, if <code>NewString</code> returns
376a non-NULL value, you don't need to check for an exception. However, if
377you call a method (using a function like <code>CallObjectMethod</code>),
378you must always check for an exception, because the return value is not
379going to be valid if an exception was thrown.</p>
380
Elliott Hughes868d74e2011-09-27 16:27:31 -0700381<p>Note that exceptions thrown by interpreted code do not unwind native stack
382frames, and Android does not yet support C++ exceptions.
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700383The JNI <code>Throw</code> and <code>ThrowNew</code> instructions just
Elliott Hughes868d74e2011-09-27 16:27:31 -0700384set an exception pointer in the current thread. Upon returning to managed
385from native code, the exception will be noted and handled appropriately.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700386
387<p>Native code can "catch" an exception by calling <code>ExceptionCheck</code> or
388<code>ExceptionOccurred</code>, and clear it with
389<code>ExceptionClear</code>. As usual,
390discarding exceptions without handling them can lead to problems.</p>
391
Elliott Hughes43873352011-07-20 15:02:35 -0700392<p>There are no built-in functions for manipulating the <code>Throwable</code> object
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700393itself, so if you want to (say) get the exception string you will need to
Elliott Hughes43873352011-07-20 15:02:35 -0700394find the <code>Throwable</code> class, look up the method ID for
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700395<code>getMessage "()Ljava/lang/String;"</code>, invoke it, and if the result
396is non-NULL use <code>GetStringUTFChars</code> to get something you can
Elliott Hughes43873352011-07-20 15:02:35 -0700397hand to <code>printf(3)</code> or equivalent.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700398
399
400<a name="extended_checking" id="extended_checking"></a>
401<h2>Extended Checking</h2>
402
Elliott Hughes43873352011-07-20 15:02:35 -0700403<p>JNI does very little error checking. Errors usually result in a crash. Android also offers a mode called CheckJNI, where the JavaVM and JNIEnv function table pointers are switched to tables of functions that perform an extended series of checks before calling the standard implementation.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700404
Elliott Hughes43873352011-07-20 15:02:35 -0700405<p>The additional checks include:</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700406
407<ul>
Elliott Hughes43873352011-07-20 15:02:35 -0700408<li>Arrays: attempting to allocate a negative-sized array.</li>
409<li>Bad pointers: passing a bad jarray/jclass/jobject/jstring to a JNI call, or passing a NULL pointer to a JNI call with a non-nullable argument.</li>
410<li>Class names: passing anything but the “java/lang/String” style of class name to a JNI call.</li>
411<li>Critical calls: making a JNI call between a “critical” get and its corresponding release.</li>
412<li>Direct ByteBuffers: passing bad arguments to <code>NewDirectByteBuffer</code>.</li>
413<li>Exceptions: making a JNI call while there’s an exception pending.</li>
414<li>JNIEnv*s: using a JNIEnv* from the wrong thread.</li>
415<li>jfieldIDs: using a NULL jfieldID, or using a jfieldID to set a field to a value of the wrong type (trying to assign a StringBuilder to a String field, say), or using a jfieldID for a static field to set an instance field or vice versa, or using a jfieldID from one class with instances of another class.</li>
416<li>jmethodIDs: using the wrong kind of jmethodID when making a <code>Call*Method</code> JNI call: incorrect return type, static/non-static mismatch, wrong type for ‘this’ (for non-static calls) or wrong class (for static calls).</li>
417<li>References: using <code>DeleteGlobalRef</code>/<code>DeleteLocalRef</code> on the wrong kind of reference.</li>
418<li>Release modes: passing a bad release mode to a release call (something other than <code>0</code>, <code>JNI_ABORT</code>, or <code>JNI_COMMIT</code>).</li>
419<li>Type safety: returning an incompatible type from your native method (returning a StringBuilder from a method declared to return a String, say).</li>
420<li>UTF-8: passing an invalid <a href="http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8">Modified UTF-8</a> byte sequence to a JNI call.</li>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700421</ul>
422
Elliott Hughes43873352011-07-20 15:02:35 -0700423<p>(Accessibility of methods and fields is still not checked: access restrictions don't apply to native code.)</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700424
Elliott Hughes43873352011-07-20 15:02:35 -0700425<p>There are several ways to enable CheckJNI.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700426
Elliott Hughes43873352011-07-20 15:02:35 -0700427<p>If you’re using the emulator, CheckJNI is on by default.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700428
Elliott Hughes43873352011-07-20 15:02:35 -0700429<p>If you have a rooted device, you can use the following sequence of commands to restart the runtime with CheckJNI enabled:</p>
430
431<pre>adb shell stop
432adb shell setprop dalvik.vm.checkjni true
433adb shell start</pre>
434
435<p>In either of these cases, you’ll see something like this in your logcat output when the runtime starts:</p>
436
437<pre>D AndroidRuntime: CheckJNI is ON</pre>
438
439<p>If you have a regular device, you can use the following command:</p>
440
441<pre>adb shell setprop debug.checkjni 1</pre>
442
443<p>This won’t affect already-running apps, but any app launched from that point on will have CheckJNI enabled. (Change the property to any other value or simply rebooting will disable CheckJNI again.) In this case, you’ll see something like this in your logcat output the next time an app starts:</p>
444
445<pre>D Late-enabling CheckJNI</pre>
446
447
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700448
449
450<a name="native_libraries" id="native_libraries"></a>
451<h2>Native Libraries</h2>
452
453<p>You can load native code from shared libraries with the standard
Elliott Hughes43873352011-07-20 15:02:35 -0700454<code>System.loadLibrary</code> call. The
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700455preferred way to get at your native code is:</p>
456
457<ul>
Elliott Hughes43873352011-07-20 15:02:35 -0700458<li> Call <code>System.loadLibrary</code> from a static class
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700459initializer. (See the earlier example, where one is used to call
Elliott Hughes43873352011-07-20 15:02:35 -0700460<code>nativeClassInit</code>.) The argument is the "undecorated"
461library name, so to load "libfubar.so" you would pass in "fubar".</li>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700462<li> Provide a native function: <code><strong>jint JNI_OnLoad(JavaVM* vm, void* reserved)</strong></code></li>
463<li>In <code>JNI_OnLoad</code>, register all of your native methods. You
464should declare
Elliott Hughes43873352011-07-20 15:02:35 -0700465the methods "static" so the names don't take up space in the symbol table
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700466on the device.</li>
467</ul>
468
469<p>The <code>JNI_OnLoad</code> function should look something like this if
Elliott Hughes13bac602011-07-19 12:05:04 -0700470written in C++:</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700471<pre>jint JNI_OnLoad(JavaVM* vm, void* reserved)
472{
473 JNIEnv* env;
Elliott Hughes13bac602011-07-19 12:05:04 -0700474 if (vm-&gt;GetEnv(reinterpret_cast&lt;void**&gt;(&env), JNI_VERSION_1_6) != JNI_OK) {
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700475 return -1;
Elliott Hughes13bac602011-07-19 12:05:04 -0700476 }
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700477
Elliott Hughes13bac602011-07-19 12:05:04 -0700478 // Get jclass with env-&gt;FindClass.
479 // Register methods with env-&gt;RegisterNatives.
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700480
481 return JNI_VERSION_1_6;
482}</pre>
483
Elliott Hughes43873352011-07-20 15:02:35 -0700484<p>You can also call <code>System.load</code> with the full path name of the
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700485shared library. For Android apps, you may find it useful to get the full
486path to the application's private data storage area from the context object.</p>
487
Elliott Hughes868d74e2011-09-27 16:27:31 -0700488<p>This is the recommended approach, but not the only approach. Explicit
489registration is not required, nor is it necessary that you provide a
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700490<code>JNI_OnLoad</code> function.
491You can instead use "discovery" of native methods that are named in a
Elliott Hughes868d74e2011-09-27 16:27:31 -0700492specific way (see <a href="http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/design.html#wp615">the JNI spec</a> for details), though this is less desirable because if a method signature is wrong you won't know
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700493about it until the first time the method is actually used.</p>
494
495<p>One other note about <code>JNI_OnLoad</code>: any <code>FindClass</code>
496calls you make from there will happen in the context of the class loader
497that was used to load the shared library. Normally <code>FindClass</code>
498uses the loader associated with the method at the top of the interpreted
Elliott Hughes868d74e2011-09-27 16:27:31 -0700499stack, or if there isn't one (because the thread was just attached) it uses
500the "system" class loader. This makes
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700501<code>JNI_OnLoad</code> a convenient place to look up and cache class
502object references.</p>
503
504
505<a name="64_bit" id="64_bit"></a>
506<h2>64-bit Considerations</h2>
507
508<p>Android is currently expected to run on 32-bit platforms. In theory it
509could be built for a 64-bit system, but that is not a goal at this time.
510For the most part this isn't something that you will need to worry about
511when interacting with native code,
512but it becomes significant if you plan to store pointers to native
513structures in integer fields in an object. To support architectures
514that use 64-bit pointers, <strong>you need to stash your native pointers in a
515<code>long</code> field rather than an <code>int</code></strong>.
516
517
518<a name="unsupported" id="unsupported"></a>
Elliott Hughes1890b872011-12-16 13:59:54 -0800519<h2>Unsupported Features/Backwards Compatibility</h2>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700520
Elliott Hughes1890b872011-12-16 13:59:54 -0800521<p>All JNI 1.6 features are supported, with the following exception:</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700522<ul>
Elliott Hughes868d74e2011-09-27 16:27:31 -0700523 <li><code>DefineClass</code> is not implemented. Android does not use
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700524 Java bytecodes or class files, so passing in binary class data
Elliott Hughes868d74e2011-09-27 16:27:31 -0700525 doesn't work.</li>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700526</ul>
527
Elliott Hughes1890b872011-12-16 13:59:54 -0800528<p>For backward compatibility with older Android releases, you may need to
529be aware of:</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700530<ul>
Elliott Hughes1890b872011-12-16 13:59:54 -0800531 <li><b>Dynamic lookup of native functions</b>
532 <p>Until Android 2.0 (Eclair), the '$' character was not properly
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700533 converted to "_00024" during searches for method names. Working
534 around this requires using explicit registration or moving the
535 native methods out of inner classes.
Elliott Hughes1890b872011-12-16 13:59:54 -0800536 <li><b>Detaching threads</b>
537 <p>Until Android 2.0 (Eclair), it was not possible to use a <code>pthread_key_create</code>
Elliott Hughes868d74e2011-09-27 16:27:31 -0700538 destructor function to avoid the "thread must be detached before
539 exit" check. (The runtime also uses a pthread key destructor function,
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700540 so it'd be a race to see which gets called first.)
Elliott Hughes1890b872011-12-16 13:59:54 -0800541 <li><b>Weak global references</b>
542 <p>Until Android 2.2 (Froyo), weak global references were not implemented.
Elliott Hughes868d74e2011-09-27 16:27:31 -0700543 Older versions will vigorously reject attempts to use them. You can use
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700544 the Android platform version constants to test for support.
Elliott Hughes1890b872011-12-16 13:59:54 -0800545 <p>Until Android 4.0 (Ice Cream Sandwich), weak global references could only
546 be passed to <code>NewLocalRef</code>, <code>NewGlobalRef</code>, and
547 <code>DeleteWeakGlobalRef</code>. (The spec strongly encourages
548 programmers to create hard references to weak globals before doing
549 anything with them, so this should not be at all limiting.)
550 <p>From Android 4.0 (Ice Cream Sandwich) on, weak global references can be
551 used like any other JNI references.</li>
552 <li><b>Local references</b>
553 <p>Until Android 4.0 (Ice Cream Sandwich), local references were
Elliott Hughes868d74e2011-09-27 16:27:31 -0700554 actually direct pointers. Ice Cream Sandwich added the indirection
555 necessary to support better garbage collectors, but this means that lots
Elliott Hughes1890b872011-12-16 13:59:54 -0800556 of JNI bugs are undetectable on older releases. See
557 <a href="http://android-developers.blogspot.com/2011/11/jni-local-reference-changes-in-ics.html">JNI Local Reference Changes in ICS</a> for more details.
558 <li><b>Determining reference type with <code>GetObjectRefType</code></b>
559 <p>Until Android 4.0 (Ice Cream Sandwich), as a consequence of the use of
560 direct pointers (see above), it was impossible to implement
561 <code>GetObjectRefType</code> correctly. Instead we used a heuristic
562 that looked through the weak globals table, the arguments, the locals
563 table, and the globals table in that order. The first time it found your
564 direct pointer, it would report that your reference was of the type it
565 happened to be examining. This meant, for example, that if
566 you called <code>GetObjectRefType</code> on a global jclass that happened
567 to be the same as the jclass passed as an implicit argument to your static
568 native method, you'd get <code>JNILocalRefType</code> rather than
569 <code>JNIGlobalRefType</code>.
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700570</ul>
571
572
573<a name="faq_ULE" id="faq_ULE"></a>
Elliott Hughes43873352011-07-20 15:02:35 -0700574<h2>FAQ: Why do I get <code>UnsatisfiedLinkError</code>?</h2>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700575
576<p>When working on native code it's not uncommon to see a failure like this:</p>
577<pre>java.lang.UnsatisfiedLinkError: Library foo not found</pre>
578
579<p>In some cases it means what it says &mdash; the library wasn't found. In
Elliott Hughes43873352011-07-20 15:02:35 -0700580other cases the library exists but couldn't be opened by <code>dlopen(3)</code>, and
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700581the details of the failure can be found in the exception's detail message.</p>
582
583<p>Common reasons why you might encounter "library not found" exceptions:</p>
584<ul>
585 <li>The library doesn't exist or isn't accessible to the app. Use
586 <code>adb shell ls -l &lt;path&gt;</code> to check its presence
587 and permissions.
588 <li>The library wasn't built with the NDK. This can result in
589 dependencies on functions or libraries that don't exist on the device.
590</ul>
591
592<p>Another class of <code>UnsatisfiedLinkError</code> failures looks like:</p>
593<pre>java.lang.UnsatisfiedLinkError: myfunc
594 at Foo.myfunc(Native Method)
595 at Foo.main(Foo.java:10)</pre>
596
597<p>In logcat, you'll see:</p>
598<pre>W/dalvikvm( 880): No implementation found for native LFoo;.myfunc ()V</pre>
599
Elliott Hughes868d74e2011-09-27 16:27:31 -0700600<p>This means that the runtime tried to find a matching method but was
601unsuccessful. Some common reasons for this are:</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700602<ul>
603 <li>The library isn't getting loaded. Check the logcat output for
604 messages about library loading.
605 <li>The method isn't being found due to a name or signature mismatch. This
606 is commonly caused by:
607 <ul>
608 <li>For lazy method lookup, failing to declare C++ functions
Elliott Hughes868d74e2011-09-27 16:27:31 -0700609 with <code>extern "C"</code> and appropriate
610 visibility (<code>JNIEXPORT</code>). Note that prior to Ice Cream
611 Sandwich, the JNIEXPORT macro was incorrect, so using a new GCC with
612 an old <code>jni.h</code> won't work.
613 You can use <code>arm-eabi-nm</code>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700614 to see the symbols as they appear in the library; if they look
Elliott Hughes43873352011-07-20 15:02:35 -0700615 mangled (something like <code>_Z15Java_Foo_myfuncP7_JNIEnvP7_jclass</code>
Elliott Hughes868d74e2011-09-27 16:27:31 -0700616 rather than <code>Java_Foo_myfunc</code>), or if the symbol type is
617 a lowercase 't' rather than an uppercase 'T', then you need to
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700618 adjust the declaration.
619 <li>For explicit registration, minor errors when entering the
620 method signature. Make sure that what you're passing to the
621 registration call matches the signature in the log file.
622 Remember that 'B' is <code>byte</code> and 'Z' is <code>boolean</code>.
623 Class name components in signatures start with 'L', end with ';',
624 use '/' to separate package/class names, and use '$' to separate
Elliott Hughes43873352011-07-20 15:02:35 -0700625 inner-class names (<code>Ljava/util/Map$Entry;</code>, say).
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700626 </ul>
627</ul>
628
629<p>Using <code>javah</code> to automatically generate JNI headers may help
630avoid some problems.
631
632
633<a name="faq_FindClass" id="faq_FindClass"></a>
Elliott Hughes43873352011-07-20 15:02:35 -0700634<h2>FAQ: Why didn't <code>FindClass</code> find my class?</h2>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700635
636<p>Make sure that the class name string has the correct format. JNI class
637names start with the package name and are separated with slashes,
Elliott Hughes43873352011-07-20 15:02:35 -0700638such as <code>java/lang/String</code>. If you're looking up an array class,
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700639you need to start with the appropriate number of square brackets and
640must also wrap the class with 'L' and ';', so a one-dimensional array of
641<code>String</code> would be <code>[Ljava/lang/String;</code>.</p>
642
643<p>If the class name looks right, you could be running into a class loader
644issue. <code>FindClass</code> wants to start the class search in the
Elliott Hughes868d74e2011-09-27 16:27:31 -0700645class loader associated with your code. It examines the call stack,
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700646which will look something like:
647<pre> Foo.myfunc(Native Method)
648 Foo.main(Foo.java:10)
649 dalvik.system.NativeStart.main(Native Method)</pre>
650
651<p>The topmost method is <code>Foo.myfunc</code>. <code>FindClass</code>
652finds the <code>ClassLoader</code> object associated with the <code>Foo</code>
653class and uses that.</p>
654
655<p>This usually does what you want. You can get into trouble if you
Elliott Hughes868d74e2011-09-27 16:27:31 -0700656create a thread yourself (perhaps by calling <code>pthread_create</code>
657and then attaching it with <code>AttachCurrentThread</code>).
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700658Now the stack trace looks like this:</p>
659<pre> dalvik.system.NativeStart.run(Native Method)</pre>
660
661<p>The topmost method is <code>NativeStart.run</code>, which isn't part of
662your application. If you call <code>FindClass</code> from this thread, the
Elliott Hughes868d74e2011-09-27 16:27:31 -0700663JavaVM will start in the "system" class loader instead of the one associated
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700664with your application, so attempts to find app-specific classes will fail.</p>
665
666<p>There are a few ways to work around this:</p>
667<ul>
668 <li>Do your <code>FindClass</code> lookups once, in
669 <code>JNI_OnLoad</code>, and cache the class references for later
670 use. Any <code>FindClass</code> calls made as part of executing
671 <code>JNI_OnLoad</code> will use the class loader associated with
672 the function that called <code>System.loadLibrary</code> (this is a
673 special rule, provided to make library initialization more convenient).
674 If your app code is loading the library, <code>FindClass</code>
675 will use the correct class loader.
676 <li>Pass an instance of the class into the functions that need
Elliott Hughes43873352011-07-20 15:02:35 -0700677 it, by declaring your native method to take a Class argument and
678 then passing <code>Foo.class</code> in.
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700679 <li>Cache a reference to the <code>ClassLoader</code> object somewhere
680 handy, and issue <code>loadClass</code> calls directly. This requires
681 some effort.
682</ul>
683
684
685<a name="faq_sharing" id="faq_sharing"></a>
Elliott Hughes43873352011-07-20 15:02:35 -0700686<h2>FAQ: How do I share raw data with native code?</h2>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700687
688<p>You may find yourself in a situation where you need to access a large
Elliott Hughes868d74e2011-09-27 16:27:31 -0700689buffer of raw data from both managed and native code. Common examples
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700690include manipulation of bitmaps or sound samples. There are two
691basic approaches.</p>
692
693<p>You can store the data in a <code>byte[]</code>. This allows very fast
Elliott Hughes868d74e2011-09-27 16:27:31 -0700694access from managed code. On the native side, however, you're
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700695not guaranteed to be able to access the data without having to copy it. In
696some implementations, <code>GetByteArrayElements</code> and
697<code>GetPrimitiveArrayCritical</code> will return actual pointers to the
698raw data in the managed heap, but in others it will allocate a buffer
699on the native heap and copy the data over.</p>
700
701<p>The alternative is to store the data in a direct byte buffer. These
702can be created with <code>java.nio.ByteBuffer.allocateDirect</code>, or
703the JNI <code>NewDirectByteBuffer</code> function. Unlike regular
704byte buffers, the storage is not allocated on the managed heap, and can
705always be accessed directly from native code (get the address
706with <code>GetDirectBufferAddress</code>). Depending on how direct
Elliott Hughes868d74e2011-09-27 16:27:31 -0700707byte buffer access is implemented, accessing the data from managed code
708can be very slow.</p>
Elliott Hughes10c7ceb2011-04-13 19:01:11 -0700709
710<p>The choice of which to use depends on two factors:</p>
711<ol>
712 <li>Will most of the data accesses happen from code written in Java
713 or in C/C++?
714 <li>If the data is eventually being passed to a system API, what form
715 must it be in? (For example, if the data is eventually passed to a
716 function that takes a byte[], doing processing in a direct
717 <code>ByteBuffer</code> might be unwise.)
718</ol>
719
720<p>If there's no clear winner, use a direct byte buffer. Support for them
Elliott Hughes868d74e2011-09-27 16:27:31 -0700721is built directly into JNI, and performance should improve in future releases.</p>