Static singleton lifetime in Android - android

I have some unclear situation:
Will static singletons be garbage collected after last reference holding Activity has been destroyed? Because there is no more references in Application to singleton instance. Can I then rely on singletons?
By official Android doc:
There is normally no need to subclass Application. In most situation,
static singletons can provide the same functionality in a more modular
way.
By some post:
https://web.archive.org/web/20160729201921/http://www.devahead.com/blog/2011/06/extending-the-android-application-class-and-dealing-with-singleton/
While developing an application, I found
that sometimes some static variables bound to activities happened to
be uninitialized even though they’ve previously been initialized! I
thought that when a static variable is initialized it stays so for the
entire life of the application, but this doesn’t seem to be the case.
In another words, if nothing is holding a reference to my static singleton class, what's to prevent it from being garbage collected and destroyed?

No, because if it's a singleton, it's stored as a static field in its class, and usually singletons are not destroyed by clients, ie you wouldn't put a static method deleteInstance() which sets the reference to null so that if nobody else uses it, it's eligible for garbage collection. For static fields, garbage collection will happen when the classloader which loaded the class is discarded.
For this reason, the keyword static itself may cause memory leaks, if it references Activity objects, so you should be very careful when using it.

Yes. Every time you leave your application (for example your app opens the camera app to take a picture, or opens the browser to open a link, or the user just pushes the back button) there is a possibility that your Application object will be destroyed and recreated when you navigate back to your app.
You should initialize any static variable in a static {} block in your custom Application class if you have one, or in your Activities to ensure they won't be null.
Note that it is more probable to experience this issue on devices with weaker hardware, lower memory, but you should expect it can happen on any device.
Bottom line is, in android, don't expect that your static variables will stay in the memory at any time. Always check if they exist and reinitialize them if necessary at the right places.
EDIT:
I know it has been a long time, and I totally forgot about this thread, anyway, here is the source from the official Android lifecycle documentation:
http://developer.android.com/training/basics/activity-lifecycle/recreating.html

You can not control when exactly Java objects become garbage collected. An object becomes eligible for garbage collection when there are no more (non-circular) references to it. With Android, further, you can not control when your Activity gets removed from memory.
singletons are supposed to represent something which always exist.
You can't force any object to be garbage collected; you can request that the garbage collector runs with System.gc() but it's only a request.
If you want to make a "singleton" eligible for garbage collection, you'd probably want to have a method to set the static variable to null (and hope that nothing else had taken a copy of the reference). Obviously the next time anyone asked for an instance, it would need to be recreated. at which point it's not really a singleton, of course.

All singleton object will stay even if the activity is destroyed.

Related

How long do classes with static methods live in Android?

This is a follow up question to one of my previous questions.
I have a LoadingActivity which loads some graphics needed by all Activities and store it into a static class. I try to not load the LoadingActivity over again when pressing HOME and resume the app since it takes a lot of memory and runs out of it after several times whereby the graphics are already loaded, so no need to start the LoadingActivity again.
My question is, how long does the static class live? Can I rely on it's availability after resuming the app, or may it be here since Android kills it due to memory issues or is it always here as long as the vm runs (that means as long as the phone is running)?
As Simon points out, "static class" means different things in different languages, and Java does not have anything quite like the static classes in some other languages. But I don't think that's what you're talking about. You seem to be asking whether objects referenced by strong static references can be garbage collected. If so, the answer is no.
A class is represented by an object of class Class which is reachable via its ClassLoader. Anything referenced by the Class will therefore be reachable as long as the ClassLoader is reachable, which in the case of the system classloader is as long as the Java/Dalvik VM exists. But that is not as long as the phone runs, since an independent VM is created for each app. The entire process and VM in which an app is running may be killed whenever the app is in the background. When you return to the app, its classes will be reloaded.
If static fields are really the best choice, as opposed to a ContentProvider or foregound Service, then every time your app resumes you will need to check if the static references have been initialized and re-initialize them if they are null.

Android: Is it safely to store global listeners in global list?

Sorry for my English
I have some class that has static (== global) methods such as setListener(), removeListener(). It stores quite few listeners (which are global) and these listeners take very low memory.
But what will happen if the system kills my app's activity because of the lack memory for other application?
Could happen that the system will remove these global listeners?
If the system kills your app, it kills the VM - static variables are lost.
Depending on what you're doing, you probably don't want to register short lived listeners in a static way.

Storing data in static objects without memory leaks

I'm trying to track down an issue where some users have started getting out of memory errors in KitKat. I've not seen them in previous versions but I know memory usage has sometimes got much higher than I'd expect.
I'm trying to go through the app identifying things that are stored in static variables at the moment within the app and there's a few that I was wondering if they would cause issues.
They are:
Notification //as in when a notification is raise
PendingIntents
BroadcastReceiver //as in the object passed to: context.registerReceiver
SharedPreferences
From what I can tell I don't think these hold the context objects, but I'm not sure.
I try to make sure when using context objects I'm only using Activity contexts when the scope is only applicable for the activity and when that context is needed. For other situations I use the application context.
I would suggest you to run your app and use all activities your app contains of and also switching orientation several times, then exit the app and trigger a GC (there's buttons for all of this) after that dump a hprof (this asumes you are using Eclipse) and fire the leak suspects report, use the histogram button to view what allocations have been done and sort of #objects (try to filter on your package name since String / byte[] etc tend to dominate such a leak suspect report even though the don't have to be leaks). A guide to: debugging memory in Android.
As for your questions to those specific classes (when i say, "could leak a context" i mean activty context, since application is singleton):
Notifications are preferably handled by the Notification.Builder, that one takes a context so holding on to notification in a static variable could leak a context
PendingIntents are obtained from helper methods where context are sent in see PendingIntent could leak context as well
BroadcastReceivers can be registered in manifest (not leaking context here) or at run time, if you are not unregistering in onPause (registering in onResume) you could leak the BroadcastReceiver which in turn leaks the current activity context (this)
SharedPreferences are fetched from the current activity if your activity gets recreated there might be a leak as well
This is a hard topic, that's why i suggest you to profile your are app i suggest in the top of this answer. Other than that i don't quite get the point of holding on to several of the asked classes as static instnace variables, what do you want to achieve with that? Especially if you are not sure if you leak contexts or not.

Static stuff in a Activity

Why I shouldn't use static objects in an Activity or don't make static calls to an Activity?
A more reasonable statement would be saying be extremely careful about using static variables in Android.
You can use them, but be aware that you application can and will be killed by the OS, and restarted when the user returns to the app (i.e. maybe from the recent apps list). This results in your application having many different entry points, and you can't assume the static variable will be initialized.
For example, setting a static variable in your application's first Activity, and assuming it will always be set is a big mistake.
Also, be cautious about storing anything that has a reference to an Activity as a static variable, because this tends to be a common source of consuming memory unnecessarily. For example, storing a View in a static variable is almost certainly a mistake, because it will prevent an entire Activity from being garbage collected if not cleared out.
It is a general good practice to avoid making things static that don't need to be since they increase the chances of memory leaks. If you're always holding a reference to some data the GC won't be able to free it.

How to track down memory leak - Find living references

I have a fairly complex app -
The UI Activity launches a Service and sets up 2 way AIDL callbacks so the two can communicate.
The service runs forever (unless hits 'off' button in UI Activity).
The problem is when the user exits the Activity, the Activity memory is not released.
-The amount of memory used by my app is the same even if the UI Activity has been closed.
-The heap still shows mapTiles and other UI crap on it even if the UI Activity has been closed.
So my guess is somehow the Service is holding references to the Activity. I know the many articles warning about leaking the Activity Context. The Service only references the Activity through a Weak Reference stored at Application scope. (a class that extends Application)
Is there any way to find what specifically is referencing the Activity? The dominator tree shows mapTiles and ListView layouts eating all my memory... but I can't find the reference to the Activity which is keeping that stuff alive.
Also, is there a way to dump an HPROF heap dump thing if OutOfMemoryException occurs?
The problem is when the user exits the
Activity, the Activity memory is not
released.
There is no "exit Activity" in Android. Calling finish() or pressing back on the activity does not remove objects from memory that the activity used. Android inherently takes care of this itself at some random point in the future.
If you want your objects to be released from memory at the moment the activity finishes, you need to manually release them yourself.
Edit: The class that can be used to find memory usage is the ActivityManager.
If it's not yourself who is holding a reference ("references the Activity through a Weak Reference stored at Application scope", do you null it? I wonder why you reference the activity in the service, usually its the other way), did you try to execute a GC? As long as there is enough memory left, no gc will take place to move the trash away.

Categories

Resources