Qs on JNI_OnUnload() and de-initialization

Showing 1-4 of 4 messages
Qs on JNI_OnUnload() and de-initialization Lewis Z. 7/2/09 9:20 AM
Debugging my code, I found out that JNI_OnUnload() was not always
called even though onDestroy() was already called. Why? Should
JNI_OnUnload() be called after an activity is destroyed?

When my application exits, I have to free up memory and do other clean-
ups in JNI. I thought these should be done right after
UnregisterNatives and DeleteGlobalRef's were called. If JNI_OnUnload()
is never called, then my application has a lot of memory and resource
leaks.

Any suggestions? Thanks.
Re: Qs on JNI_OnUnload() and de-initialization fadden 7/2/09 10:25 AM
JNI_OnUnload is never called on Android, because the shared library is
never unloaded.  It can't be, unless any code that potentially uses it
is also gone.

In an ideal world, this would simply mean that the relevant class
loader, and all classes loaded by that class loader, are unreferenced
and can be garbage-collected.  With native code the world is rarely in
an ideal state, and if bits of native code manage to share parts of
themselves then things can get ugly.  One way this commonly goes bad
is when there's a C++ object lurking somewhere and the destructor gets
called.  If we've dlclosed the shared library, the process will crash.

At any rate, the Android lifecycle doesn't really support an
"application exit" -- either your app lurks quietly until something
needs it, or the system kills it abruptly when it needs the memory for
something else.  Because the system works this way, support for class
unloading has not been implemented yet, and is not at the top of the
feature list.

It sounds like you want to explicitly manage resources allocated in
native code.  You should not rely on JNI_OnLoad / JNI_OnUnload to do
that.  Even on a non-Android system you're likely going to get in
trouble, because if you're holding global references to app classes,
those references would prevent the classes from being unloaded and
JNI_OnUnload would never be called.  Instead, use explicit startup/
shutdown calls at appropriate points in your Android app.

Incidentally, there's no need to use UnregisterNatives -- the methods
are presumably registered to a class that is getting discarded.  In
fact, the JNI spec says you shouldn't use it:

  "This function should not be used in normal native code. Instead, it
provides special programs a way to reload and relink native
libraries."
Re: Qs on JNI_OnUnload() and de-initialization Lewis Z. 7/2/09 11:37 AM
fadden, thanks a lot for the detailed information.

When I said "application exits", does onDestroy() imply it? Everytime
I tap the Back key, my application will go through OnPause(), onStop()
to onDestroy(). It doesn't stay in onStop(). Why?

My alternative place for de-init is finalize(). But I don't see this
method called either. So is it safe to put de-init logic in onDestroy
()?
Re: Qs on JNI_OnUnload() and de-initialization fadden 7/2/09 2:27 PM
On Jul 2, 11:37 am, "Lewis Z." <lzh...@gmail.com> wrote:
> When I said "application exits", does onDestroy() imply it? Everytime
> I tap the Back key, my application will go through OnPause(), onStop()
> to onDestroy(). It doesn't stay in onStop(). Why?
>
> My alternative place for de-init is finalize(). But I don't see this
> method called either. So is it safe to put de-init logic in onDestroy
> ()?

Avoid finalizers if at all possible.  (See Effective Java for a list
of reasons.)

http://d.android.com/guide/topics/fundamentals.html says:

  'The entire lifetime of an activity happens between the first call
to onCreate() through to a single final call to onDestroy(). An
activity does all its initial setup of "global" state in onCreate(),
and releases all remaining resources in onDestroy(). For example, if
it has a thread running in the background to download data from the
network, it may create that thread in onCreate() and then stop the
thread in onDestroy().'

So, anything created in or after onCreate() should be discarded in or
before onDestroy().