Question

I have basic ndk project: NdkTest.java class and ndk.cpp file.Now I have C++ object that should be created once, and destroyed when application is killed or closed. So my NdkTest.java looks like this:

NdkTest {
    static {
        System.loadLibrary("testLib");
    }
    public static native method1();
    public static native method2();
}

ndk.cpp looks like this:

#include <jni.h>

extern "C" {
    void packageName_ClassName_method1(Env *, class);
    void packageName_ClassName_method2(Env *, class);
}

ManagerClass *manager = NULL; //this is actually in .h file but for simplicity of this example I put it here

void packageName_ClassName_method1(Env *env, class clazz) {
    if(manager==NULL) {
        manager = new Manager();
    }
    manager->method1();
}

void packageName_ClassName_method2(Env *env, class clazz) {
    if(manager==NULL) {
        manager = new Manager();
    }        
    manager->method2();
}

Now... manager should be created only once and it should be used by all my native methods. This code will compile and work but it will cause memory leaks because manager is never destroyed. Where should it be destroyed? Of course I can create java methods like createManager() and destroyManager() but I don't want to do that. Is it even possible? I tried making Manager object global like this:

ManagerClass manager;

void packageName_ClassName_method1(Env *env, class clazz) {    
    manager.method1();
}

void packageName_ClassName_method2(Env *env, class clazz) {    
    manager.method2();
}

And it also works but I don't know if it's destructor is ever called. I put log in there but it has never shown.

So my question is: What is the best way to deal with releasing memory in Android native development? Is there any good pattern? If the only way is to create java methodscreateManager() and destroyManager() then where should I call destroyManager()? Java finalize() is not guarenteed to be called so where should I put it?


I have found great video on this topic:

About 31min. is the best part :)

Was it helpful?

Solution

With Android model of memory management, there is no guarantee that any destructor will be called. The only guarantee you have by the book is that the onPause() method will be called for the foreground activity.

OTOH, the Linux kernel takes care of releasing all resources that had been used by a process that shuts down either gracefully or by force.

Therefore unless your Singleton locks some very special system resource which cannot be reclaimed automatically by the kernel, you should not worry about it's destructor. But if it does (e.g. of it locks the Camera), you need a bulletproof mechanism to unlock this resource as early as possible, preferably in onPause().

All this discussion does not apply to creation of a Singleton. You may use any of the methods you described above, and chose the one that fits best with your architecture. Only keep in mind the race situations when the app destruction sequence may start while the Manager object is still being created (only likely in a multithreaded scenario).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top