30

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?

Gabor
  • 7,352
  • 4
  • 35
  • 56
Arvis
  • 8,273
  • 5
  • 33
  • 46
  • 1
    @Arvis What you can rely on is global static variables. Those won't be garbage-collected until your application's process is killed by the system. – IgorGanapolsky Apr 04 '13 at 13:13

4 Answers4

19

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.

Raffaele
  • 20,627
  • 6
  • 47
  • 86
  • 37
    That is not true in android. The dalvik VM may destroy the classes along with any static variables when the application is not in the foreground, and the device needs to free up memory. – Adam Monos Dec 15 '12 at 10:04
  • 3
    Where did you read it? Android can destroy activities when they are not in the foreground, but doesn't break Java rules. In fact, if your activities are referenced anywhere, they can't be garbage collected and you have a leak. There's a post by Romain Guy about this. Don't expect Android to be a *crazy* system and just destroying objects around when memory is low. – Raffaele Dec 15 '12 at 10:10
  • 7
    I experienced it. On devices with weak hardware it's very often that any time your app goes to the background your Application object along with your activities will be destroyed and then recreated in the background. In this case even your static variables become null if you don't initialize them in a `static {}` block. Here is an SO thread about this http://stackoverflow.com/questions/9541688/static-variable-null-when-returning-to-the-app – Adam Monos Dec 15 '12 at 10:14
  • 1
    What you describe is standard behavior. If the process is killed, so are all of the classes. It's not that **within the same process** (for example switching Activities in the same app) a class object is suddenly removed. At least, this is not documented and it never happened to me – Raffaele Dec 15 '12 at 10:24
  • Yes, that's why i wrote "when your app is not in the foreground" in my answer. I think we had a slight misunderstanding – Adam Monos Dec 15 '12 at 10:25
  • 9
    Maybe, but the point is that once the process is killed, it's not that *the static field is set to null*. Simply, the app is bootstrapped again, so are all of the class objects, and so are all of their fields. It doesn't break standard Java, because the app is started again from scratch – Raffaele Dec 15 '12 at 10:29
  • Yes, but in android it is possible that the class is unloaded before the process gets killed. Just imagine a scenario when you have tons of static variables in every activity you have, taking up loads of memory. It would be unreasonable to keep them in the memory when the `Activity` isn't currently in use even though the process is still alive. That's why we have the lifecycle methods, so we can ensure that the `Activity` is recreated the same state it was before, no matter what happens in the background. – Adam Monos Dec 15 '12 at 10:34
  • 1
    Lifecycle methods regard the Activity **object**, not the Activity's **class object**. You don't create activities by hand (ie `new Activity()`), so there are no activity references around, so it's safe to assume that the system manages the objects. On the contrary, Java classes and static fields can be safely accessed anywhere, and there is no remark in the documentation that the ClassLoader unloads classes when memory is low. You simply have a leak and the app finally crashes. However, I'm putting up a demo – Raffaele Dec 15 '12 at 10:41
  • 6
    @AdamL.Mónos [Here is a demo project](https://docs.google.com/open?id=0B7Cy5X-NhwtKX1J2NDE0QTByOWM). The first activity holds a static field which takes up more memory at each `onResume()`. Note that `onResume()` must be called after `onPause()`, which means that the Activity left the foreground and could be destroyed. Still the static field is never unset, and it eventually fires an `OutOfMemoryError` – Raffaele Dec 15 '12 at 11:02
7

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

Adam Monos
  • 4,287
  • 1
  • 23
  • 25
  • 1
    If application process is killed - that is ok and there is no problem, the next time I run a fresh process must be created and all will be re-initialized. But I talked about when Activity was killed or destroyed. – Arvis Dec 15 '12 at 10:27
  • When your activity is in the background there is a possibility that the class will be unloaded and recreated when you navigate back later, so the same applies. Everything that is not in the foreground are a subject to destruction / recreation, although your `Application` is safe, until you leave your app completely. – Adam Monos Dec 15 '12 at 10:30
  • But you miss a point - what suppose to happen with my singleton what was instantiated in that Activity? – Arvis Dec 15 '12 at 10:33
  • If the `Activity` is unloaded, then so does your singleton. If you want your singleton to be kept throughout your whole application lifecycle (until you completely leave your app), then keep it in your `Application` class. – Adam Monos Dec 15 '12 at 10:36
  • So, how then a singleton can replace Application class as android try to encourage us? (There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way.) – Arvis Dec 15 '12 at 10:58
  • That rises new question: what for we use singletons in android in the first place? In my particularly case to globally share variables between activities and what the point of it if singletons may be unloaded when Activity has been destroyed? – Arvis Dec 15 '12 at 11:03
  • Well, you shouldn't use singletons to share data across activites, that's why you have intents and extras. If you have some application-wise data (login information for example) then extend the `Application` and store them there. You can use singleton in android too, just be careful where you create them first. If you keep them in activites only, then they are subject to the destruction of the activities. Keep them in the `Application` class as well, so they would be tied to your whole app, not just a part of your app. – Adam Monos Dec 15 '12 at 11:11
  • Using Intents to pass for example active TCP Socket connection between activities definitely is not a best way. Beside what the point to keep references to my singletons in Application class? It is easier and logicly to keep references to all my interested object directly without singletons at all! – Arvis Dec 15 '12 at 11:59
  • 2
    @Arvis don't worry about singletons. [Here is a test](https://docs.google.com/open?id=0B7Cy5X-NhwtKX1J2NDE0QTByOWM) that demonstrates they are never thrown away. BTW, why you need to share a raw socket? If your question is not theoretical, but instead it's application-specific, add more information and we'll answer. The post you quoted seems simply wrong: unless it can be reproduces or a document is linked, we can't assume that static fields (ie Class instances) are unloaded at runtime while the application process is alive – Raffaele Dec 15 '12 at 12:49
  • @Raffaele the [same problem]( http://stackoverflow.com/questions/5105097/static-references-are-cleared-does-android-unload-classes-at-runtime-if-unused) About sockets, i prefer not to use services, so singletons are my option: [Tcp connections in Android](http://mytechaddiction.blogspot.com/2012/05/tcp-connections-in-android.html) and [another discusion](https://groups.google.com/forum/?fromgroups=#!topic/android-developers/yxOzuMGlcSo) – Arvis Dec 17 '12 at 10:45
  • 3
    @Arvis if you look at the answers to that question, all of them agree that classes are not unloaded while the process is alive. So, again, you shouldn't worry about your static field suddenly becoming null – Raffaele Dec 17 '12 at 10:53
  • 1
    @AdamL.Mónos Interesting, that this one answer only has two different opinions: "If the Activity is unloaded, then so does your singleton" and "don't worry about singletons...they are never thrown away" :) Anyway, thanks for helping out. – Arvis Dec 17 '12 at 15:03
  • 1
    @AdamL.Mónos: "the __class will be unloaded__ and recreated when you navigate back later" --> docs please – Mr_and_Mrs_D Nov 08 '13 at 17:39
3

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.

Sahil Mahajan Mj
  • 11,033
  • 8
  • 53
  • 100
  • Exactly: singletons are supposed to represent something which always exist. But that is not always true. And therefore i can't rely on singletons! – Arvis Dec 15 '12 at 10:20
  • 1
    @Arvis Application class will be the last one to be destroyed, and the singletons it holds will live longer than any other activity which uses them. – S.D. Dec 15 '12 at 10:56
  • 2
    @Singularity In a case of custom Application class all are clear, but i'm trying to understand how to use singletons instead of Application class (what beside is singleton too) as android encourage us: "There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way." – Arvis Dec 15 '12 at 11:08
-4

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

Nasif Noorudeen
  • 143
  • 2
  • 15