1

Let's say I start from activity A -> activity B. While in activity B I press home to exit. After a long time, gc may be called because other apps take higher priority. My question is, which of the following type of data will be garbage collected (I'm pretty sure static fields can be garbage collected any time but I'm not sure about these):

i) fields that are declared final or static final

ii) intent and its data that I passed from activity A to activity B

iii) onSavedInstanceState when orientation is changed during the app running

I ask this because I want to ensure that my app won't crash when I restore activity B from background after a long period.

Neoh
  • 15,906
  • 14
  • 66
  • 78
  • 1
    Anything you don't hold a reference to may be garbage collected. That's how garbage collection works. It doesn't matter how variables are declared - if you can still access them then they will not be collected. – Alex MDC Jul 03 '13 at 09:12
  • does that mean it is not safe to call `getIntent()` after I restore the activity from background?3 – Neoh Jul 03 '13 at 09:17
  • It is safe! Everything is safe. If your activity is going to be destroyed then `onDestroy()` will be called to let you know, which should be the last time you ever see the activity. You should not be keeping a reference to the activity from any other Android component (e.g. in your application) so should never be able to get hold of the activity again after it has been destroyed. – Alex MDC Jul 03 '13 at 09:25
  • I've added a proper answer below, I hope that clears up some of your questions. If not, let me know :) – Alex MDC Jul 03 '13 at 09:42

4 Answers4

2

Static variables cannot be elected for garbage collection while the class is loaded. They can be collected when the respective class loader (that was responsible for loading this class) is itself collected for garbage. (see this answer)

Other than that your object with every instace variable can be gc if you design your app correctly and do not hold onto references of Activities, Fragments, etc. yourself. But don't worry about that the Android lifecycle takes care of that for you, it will provide the an activity that was destroyed/gc with your bundl that you have saved onSavedInstanceState onCreate() and so on, so you can retrieve that state you had before going to background

Community
  • 1
  • 1
Patrick
  • 33,984
  • 10
  • 106
  • 126
  • Say a `public static final` string is created in activity A, then I go to activity B which reference this string, and press home to exit. I'm sure activity A can be garbage collected, in this case will the `public static final` string be collected too? – Neoh Jul 03 '13 at 11:15
  • static variables are not in any specific instance of your class (hence they are called class-variables instead of instance-variables), they are "global" for all instances, so a garbage collected activity instance wont affect static variables – Patrick Jul 03 '13 at 12:26
1

I think you are confusing the concept of garbage collection with the component lifecycle that Android provides.

Garbage collection will only free objects sitting in memory if they are no longer reachable, that is no more strong references to them exist. If you are using finalizers to trigger behavior when an object is collected then there is you are doing something wrong.

Meanwhile, the component lifecycle is managed by the Android OS in a determinate fashion - when it wishes to kill an activity (or service, or application) then it will call some methods on that component (e.g. onDestroy()) and that's it - once Android has destroyed it then it should be gone from your perspective to.

The only difficulty comes in when you wish to start saving and restoring activity state - then it becomes important to you to manage a few things when your activity is being paused/stopped/destroyed. Again, these are fully determinate events and unrelated to garbage collection.

To answer your questions specifically:

i) it doesn't matter how fields are declared. If you have a reference to an object then you automatically have a reference to all of its fields, meaning they won't be garbage collected.

ii) when you create the intent, do you keep a reference to it? If not, then it may be garbage collected, but this should not bother you because you don't have a reference to it anyway :)

iii) saved instance state will be kept by the Android system and given back to you when the activity is recreated. You should not keep your own reference to it.

Hope that helps!

Alex MDC
  • 2,416
  • 1
  • 19
  • 17
  • but from what I read in [here](http://stackoverflow.com/questions/15964411/app-crashes-when-restoring-from-background-after-a-long-time) and [here](http://www.thekirankumar.com/blog/2013/02/15/android-contexts-and-singletons/#more-989) data from activity A can be garbage collected even if activity B is referencing them. – Neoh Jul 03 '13 at 10:12
  • Activity A can be _destroyed_ while it is in the background, certainly, but in that situation onDestroy() will be called on it. If the user later returns to Activity A then it will be recreated with any saved instance data. Activity B should not hold any references to activity A, that is why data is passed back and forth via `Intent` objects. – Alex MDC Jul 03 '13 at 10:39
  • Just to add, it's very very bad practice to hold onto references on any android instance (Activity, Fragment, View,...) because you create memory leaks. Android Design is based on the concept that activties can be destroyed any time, so devs should design their apps with this in mind. – Patrick Jul 03 '13 at 14:53
  • @AlexMDC - you are partially incorrect. Static fields *can* be garbage collected if Dalvik is closed and the task is recreated from the "Recent tasks" list. Rare case but it's a cautionary tale why you should always save things to disk/Parcels. – Delyan Jul 03 '13 at 15:01
  • @Delyan do you have a reference for that? The case you are describing sounds like the whole process has been destroyed and the activity is then started in a new task in a new instance of the application. If so then that's hardly surprising :) – Alex MDC Jul 03 '13 at 15:15
  • The best way of testing some weird application behavior is to use special apps like FastReboot or some kind. They simulate the situation when ActivityManager has to kill all of the activities in background due to lack of memory. When you return to your activity after running such an application your `onCreate()` **WILL NOT BE CALLED** (hence no possibility to reuse saved state). Instead you will probably receive a bunch of NullPointerExceptions when your fields are no longer available. Still do not know how to effectively deal with such situations... – Alex Semeniuk Feb 13 '14 at 10:32
0

Your activity can be garbage collected and recreated again when restoring from background. If you want to save some data, use SharedPreferences or other persistent storage.

SpongeBobFan
  • 964
  • 5
  • 13
0

This thread is old but does not address a very important point from: https://developer.android.com/topic/performance/memory#release

Android can reclaim memory from your app in several ways or kill your app entirely if necessary to free up memory for critical tasks

at any time.

Killing your app process means it restarts which implies that if you have not saved any state into the bundle, db, or sharedprefs, it will be re-initialized. There are also the ComponentCallbacks2interface callbacks to listen for low memory events.

.

Droid Teahouse
  • 893
  • 8
  • 15