0

I'm trying to understand the lifecycle stages of an Android app with a native lib.

The native library is loaded like this in the MainActivity:

static {
        System.loadLibrary("lifecycleevents");
}

The definition of JNI_onLoad and JNI_onUnLoad are as follows:

extern "C" JNIEXPORT jint JNICALL
JNI_OnLoad (JavaVM * pJavaVM, [[maybe_unused]] void * pReserved) {

    JNIEnv *    env;

    if (pJavaVM->GetEnv ((void **) &env, JNI_VERSION_1_6) != JNI_OK)
        return JNI_ERR;

    __android_log_print (ANDROID_LOG_VERBOSE, (const char *) TAG, "JNI_OnLoad");

    return env->GetVersion ();
}

extern "C" JNIEXPORT void JNICALL
JNI_OnUnload (JavaVM * pJavaVM, [[maybe_unused]] void * pReserved) {

    __android_log_print (ANDROID_LOG_VERBOSE, (const char *) TAG, "JNI_OnUnload");
}

I'm able to trace JNI_onLoad but JNI_onUnLoad never hits. According to the documentation, it will be called when the classloader of the native lib is garbage collected. This will happen at some point after MainActivity's onDestroy but before the app terminates, right? So, why is JNI_onUnLoad not called?

Also, in the documentation, JNI_onUnLoad_L will be called when the classloader of the native lib L is garbage collected. Since my native lib name is lifecycleevents, I renamed the JNI_onUnLoad method to JNI_onUnLoad_lifecycleevents, but it still doesn't get called.

I'm confused. Are both the methods valid? Requesting help from anyone who is familiar with this topic.

NightFuryLxD
  • 847
  • 5
  • 15
  • 1
    Well, [this commit](https://android.googlesource.com/platform/art/+/598302a%5E%21/) suggests that native libraries are indeed unloaded on Android if the classloader get garbage collected. But I don't know exactly when your classloader would get garbage collected. – Michael Dec 07 '21 at 13:19
  • 1
    I do not think the classloader associated with the app is _ever_ garbage collected. why not put your logic in `onDestroy`? – Botje Dec 07 '21 at 14:57
  • @Botje, This is for native libs. JNI_onUnload is the place to delete global references and unregister natives....and it seems we cannot explicitly invoke unload the library like its done using System.loadlibrary. – NightFuryLxD Dec 07 '21 at 16:26
  • @Botje, Btw, onDestroy is not reliable. When I kill the application (swipe up the app), sometimes it stops with onStop. Have tested this myself. Anyway, according to this [answer](https://stackoverflow.com/questions/43412630/release-resources-in-onpause-instead-of-ondestroy), it is not optimal to use onDestroy to finalize resources. – NightFuryLxD Dec 07 '21 at 16:29
  • @Michael, Thanks. But the classloader will get garbage collected at some point before the app terminates right? At that time, I expect to see the log. Pls let me know if I'm misunderstanding something. – NightFuryLxD Dec 07 '21 at 16:36
  • 1
    Android does not support unloading native libraries. Furthermore, Android does not guarantee that any of the shutdown code of your app (onDestroy and such) will have a chance to run. You should not rely on that; if you need to do something really important, put it into onPause() – this is guaranteed to be called. – Alex Cohn Dec 07 '21 at 19:15
  • @AlexCohn, You cannot explicitly unload native libs, thus I can't do this in onPause. When the activity is garbage collected, according to JNI documentation, JNI_onUnload will get called. So, at some point, for whatever reason, Android can destroy the activity...at that time, won't JNI_onUnload get called? – NightFuryLxD Dec 09 '21 at 03:26
  • `JNI_OnUnload` will not be called on activity destruction. The native libs are not related to activity livecycle at all. The libraries may be unloaded on **application** destruction, but *a)* as I explained, there is no guarantee and *b)* the process cleanup will happen by the rules of Linux anyways, so anything you do in `JNI_OnUnload` will not have a value for you. – Alex Cohn Dec 09 '21 at 08:28

0 Answers0