6

This is about Android. The situation:

C++ library and java wrapper classes plus native functions (JNI) for working with C++ classes from the library. When common java code needs C++ object, it creates corresponding java wrapper object which creates C++ object through native function and remembers the pointer to the native object in 'long' variable. In all next actions the wrapper gives this pointer to the native functions etc.

The problem:

How to release all allocated C++ objects at the end? Currently every wrapper class has 'finalize' method where it calls native function for releasing of the C++ object, but Android doesn't guarantee the calling of 'finalize'! At the other side, normally the C++ library has no idea how many and what types of C++ objects are allocated by java code.

What will happens with the remaining allocated memory when our java application terminates, will Android release automatically the whole heap, used from the native library, when the OS unloads the library?

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
ggurov
  • 1,496
  • 2
  • 15
  • 21
  • You'll find the answer you need here: http://stackoverflow.com/questions/2506488/java-finalize-method-call – JACH Sep 22 '11 at 20:42
  • 2
    The essence of the discussion there is "finalize is not sure", which I pointed out in my question here. The proposal of @rsp is suitable only for simple cases - when the whole object's lifetime lies in continuous piece of code. Todays event-driven programming contains often more complicated scenarios. – ggurov Sep 23 '11 at 11:00

3 Answers3

3

At the end of the process lifetime, all process memory (both Java and C++ heap) will be freed and reclaimed by the system. One thing is though, Android activity closing does not necessarily end the process. I'm not sure what's the process shutdown policy there.

On the other hand, relying on the garbage collection and finalize() sounds like solid design to me. You claim - "Android does not guarantee finalize()". Do you have a cite for that? 'Cause if it comes with a disclaimer of "when the object is freed as a part of process shutdown...", then we're still good.

And if you're super-paranoid, you can write your own malloc()/free()/realloc() wrapper, store a list of all allocated objects, and introduce a cleanup function that walks the list and frees them all. The containing Java objects, however, might end in a weird zombie state where the memory has been freed from under them. This is a tricky proposition that is very easy to get wrong. So I'd still say - have faith in the garbage collector. Lack thereof would be... disturbing.

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • "At the end of the process lifetime, all process memory (both Java and C++ heap) will be freed and reclaimed by the system" - if this is for sure, it is enought for me. "Android activity closing does not necessarily end the process" - yes. It needs some time after finishing of main activity, or it can be forced with System.exit or android.os.Process.killProcess. "Do you have a cite for that?" - not exactly, but this is my impression from cited here links and other ones which I read before. In reality I tested it, placing Log.w in finalizer - no any message before or after dieing of the process – ggurov Sep 23 '11 at 13:12
  • "And if you're super-paranoid, you can write your own..." - yes, I considered something similar. With cleanup started on JNI_OnUnload(). Unfortunately JNI_OnUnload is never called also. And if it is for sure that the system will free everything on lib. unload, no need to waste my time to write such cleanup. – ggurov Sep 23 '11 at 13:24
1

Due to the difference in paradigms, you have to incorporate explicit destruction into your Java objects that are implemented under the hood using C++ resources. So a close() or other such method. The same issue comes up with the JNI, so answers to those questions will apply to you:

Force Java to call my C++ destructor (JNI)

As for the memory issue on closing, it's generally best in my opinion to not rely on this. If you get to a clean state, valgrind and such can make sure you weren't leaking.

But from a technical standpoint--since Android is based on Linux, I'd imagine it does the usual thing and will free all the memory when the process closes. Taking advantage of that can make your program exit faster than explicitly freeing memory (for experts only who use other methods to ensure this maintains program correctness and they aren't leaking at runtime).

Community
  • 1
  • 1
  • About your link, see my answer to JACH, the problem is the same. Some wrapper of C++ object can lie deep in the program's hierarhy of objects and about top levels of this hierarhy no one would know for it. "I'd imagine it does the usual thing and will free all the memory when the process closes" - I hope. – ggurov Sep 23 '11 at 12:58
0

We are using JNIs and we had a problem like that

Actually, the problem resided in the fact that we were overloading finalize() to do the clean up. We solved our problems by removing our finalize() and creating a clean() instead. This clean() calls the JNI function that does the appropriate deletes (and set the C++ pointers to null, just in case). We call clean() just as you would in C++ with delete (e.g. when the variable goes out of scope).

That worked for us. I hope it works for you. Good luck!

JACH
  • 996
  • 11
  • 20
  • Almost every one speaks for this method, but imagine: c++ pointer in java object X, which resides in object Y, which resides in Z. You can make method clean() in X, but you will need to define such method in Y and Z too! I.e. to emulate the c++ destructors style in your whole java program, just for every case. I prefer to think that Android will free the whole heap, this is the normal behavior which we have to expect. – ggurov Sep 29 '11 at 19:47