Unloading a Scala Object - android

I made the mistake of writing a Scala program for Android and relying on Scala Objects. Well the singletons where really handy when writing a game but now when the game ends, class instances that are loaded by the main Activity are GC:d like they should be, but the Scala Objects seem to stay in memory. So when I restart the game, the objects are in an unknown state instead of just initializing like when first starting the game.
So what would be the correct way of "destroying" these objects? In other words, how to make sure that some destroy code is run when the Android Activity ends?

You cannot. You have to turn them into classes and instantiate one instance of each in your main Game object, or whatever it's called.
Objects are singletons for the entire duration of the application (until the JVM shuts down). That's why they should typically not contain anything mutable.

Related

Android application lifecycle (with initializing static data etc)

I can't find some informations about android application (not activities) lifecycle. My question is, how the application is working, when I treat it like a java programm - when it's initializing for example static objects. I'm adding a small graphic, that is showing my point of view - I'll be greatfull if someone could tell me, if I'm thinking correct :-)
For the application lifecycle, as per Android API Guide:
By default, every app runs in its own Linux process. Android starts the process when any of the app's components need to be executed, then shuts down the process when it's no longer needed or when the system must recover memory for other apps.
For static objects, they are initialized only once and are initialized when the class (which they are member of) gets loaded by ClassLoader. They will remain in memory until the class is unloaded. To read more about it, check this SO question
For activities, they have a clear lifecycle.

Is it still the case that Android never unloads classes?

We have a large app that's always running into the dread method count limit. I've been asked to come up with a way to let it do much more, including supporting plugins. Looking for ways to unload code, I ran across JNI Tips which says
Classes are only unloaded if all classes associated with a ClassLoader
can be garbage collected, which is rare but will not be impossible in
Android.
This did seem to imply that a plugin can be unloaded if you, say,
use a new DexClassLoader for each .jar file,
only ever refer to the plugin through an interface reference, and
null-out any copies of that interface reference when done.
So, I created a test case:
I created a couple of trivial plugins, using a unique loader for each.
I created a ReferenceQueue<ClassLoader> and created weak references to my two loaders, using that queue; I created/started a thread that loops indefinitely, doing a queue .remove() and reporting.
I similarly created a ReferenceQueue<Class<?>> and created weak references to each plugin's getClass() using the queue; I created/started another thread monitoring the class reference queue.
I create a thousand 1000x1000xARGB_8888 bitmaps to thoroughly force gc.
My monitoring threads seem to work - I saw loader2 get gc-ed when I used loader1 to load both plugins by mistake ;-) - but otherwise my threads stay silent, even on 4.3. Am I maybe missing something obvious in this test case, or is it still the case that the
Dalvik VM doesn't currently unload classes
as Google employee fadden says in Android: When do classes get unloaded by the system?
The Dalvik VM still doesn't unload classes. The JNI Tips page is encouraging good behavior so your app doesn't break if the VM starts unloading classes someday.

Is it safe to use static class variables in an android application

I am aware of the technique of extending the Application class to provide global storage. However in my case I am writing a class for a library function, so do not wish to force users of the class down this path. I have a requirement for some static class variables. I have seen passing references in StackOverflow that these might not be safe. However I've tried two different applications using the same class, and even when running both applications side by side on a Galaxy S3 in multi-window mode, the static class variables remain separate.
So, can someone with an in depth knowledge of Android internals confirm if this is safe or not.
If it is not safe, I can wrap the variables in a nested class and add them to a Serializable static HashMap, using the application package name as the key. This will force them to be safe. However if this is not necessary, then I'd rather not do it.
I have seen passing references in StackOverflow that these might not be safe.
They are not "safe" insofar as your process will be terminated from time to time, wiping out your static data members (and your custom Application, for that matter). Hence, static data members are good for a cache and not much else.
Within that scope, they are "safe".
You just need to make sure that this data is either stored somewhere persistent (e.g., file) or otherwise can be regenerated once the process is terminated and later is started up again. This is no different than with Application.
However I've tried two different applications using the same class, and even when running both applications side by side on a Galaxy S3 in multi-window mode, the static class variables remain separate.
Correct. Those are separate processes, with separate copies of your class and objects.
If your goal is to store persistant data across the twists and turns of the application lifecycle, then I would recommend not using static variables to do so. The obvious problem with this approach is that they could easily be garbage collected by the system when the operating system decides to reclaim memory (i.e. when the screen sleeps or a different application starts a memory-intensive task). I'm not sure what kind of data you are looking to "store", but I would recommend saving the state in SharedPreferences or an SQLiteDatabase instead.
I'm a little confused about what you're trying to do. You're trying to create a utility library in Java to be used by other applications? You're trying to create a whole Activity intended for use by other applications?
At any rate, as other posters have mentioned, applications can be killed at almost any time when resources become tight. There's simply no way to guarantee that static global values will remain resident in memory. You must provide a way to back it up on onPause() or onSaveInstanceState().
If you're writing a utility library, I presume that it returns some master object which holds all of its state. Add saveState(Bundle), restoreState(Bundle) methods to that object, and optionally saveToSharedPreferences() and restoreFromSharedPreferences() methods as well.
If it's an Activity you're writing, you're probably already familiar with the ways of saving state.
Me, I'm fond of combining the "singleton pattern" with shared preferences: https://stackoverflow.com/a/13673178/338479
You seem to have a deep misconception of how classes work.
Even if two classes are in the same package in two separate apps (by default) those apps run on separate VMs (i.e., processes). They literally have nothing to do with each other (as it should be, since otherwise you might get cross-app name collisions which is unacceptable).
What you're looking for is not a way to use static variables but a way to do inter-process communication (IPC). Android's Services are ideal for this, though there is a bit of a steep learning curve there.

What's happenings if I don't implement the override methods in Android?

I'm developing an Android app, and I already read about the lifecycle of an activity.
I don't know, what's happens if I don't implement the methods of the lifecycle onCreate(), onDestroy(), etc..
The JVM calls automatically these methods?
I'm habitual in iOS, and the change to Java is some peculiar for me. I want call the methods to manage memory.
I'm supponing that these methods helps to manage the memory in my App and this not crash in runtime.
The Android framework always calls those methods. If you don't implement them, the base class methods will be run. Typically they do nothing (significant). However, you definitely need to override some of the methods (at least onCreate) to make your activity useful.
As far as memory management goes, you usually should not worry about that at all. Java has automatic garbage collection that works very well. Unlike Objective C, in Java there is actually no mechanism for manual memory management; it's always done by the JVM. The only thing you need to pay attention to as far as memory management goes is to be sure you don't maintain hard references to large data structures that you no longer need. See the article Avoiding Memory Leaks in the Android blog.
If a method isn't overridden its base class implementation will be used.

Native C++ library - who have to release the memory and how?

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?
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.
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).
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!

Categories

Resources