I'm thinking about using singleton patterns for adapters and helpers in an Android app that I'm building, but I'm not too familiar with Java's garbage collecting and how static attributes (eg static FooBar instance) impact memory usage.
Will it have a big enough impact in Android apps that I should avoid using it?
Depends on what you mean by "impact memory usage". An object isn't larger or smaller just because there is one instance of it enforced by a singleton pattern. In that sense there's no difference.
If it means you definitely have at most one copy of an object in memory instead of several, yes it could help.
Usually what people mean though, is, how long does the singleton live? does it stick around taking up memory when the app is in the background?
A static member is attached to an instance of its Class which is in turn attached to its ClassLoader. So the singleton lives as long as the ClassLoader. It turns out in Android that the app's ClassLoader goes away in onDestroy, not onPause, so a singleton implies you hold on to the memory even when the app is in the background.
As others have said, it depends. The case where it could be bad is if the singleton is holding references to objects that could otherwise be garbage collected. If there are a lot of references in the object, or references to large objects, you could be using memory you don't need. You could work around it by using weak references, but then you have to have code to recreate the objects when needed if they get garbage collected. You could not use the singleton pattern, which would allow things to get garbage collected (at least potentially), but at the expense of creating and throwing away objects. The best solution depends on the details of the object and its usage. One thing to always avoid is holding on to a reference to a UI object, such as a View.
Related
I'm just getting started with Android Game Development and I'm testing the libgdx Framework at the moment. I was just wondering what the importance of the dispose() method is and why it is necessary to dispose of every object there? Just to save resources?
Appreciate it.
Java is a "managed language". This means that everything (e.g. instances of classes or arrays) you use in your application automatically gets destroyed when you no longer use it. This is done by the "garbage collector". So, when you create e.g. an array (float[] arr = new float[1000];) then you allocate memory, but you never have to free that memory yourself because the garbage collector will do that for you when you no longer use the array (arr).
In some cases, however, the garbage collector can't know how to automatically free something for you. For example, when you allocate some space in video memory (VRAM) then you don't have access to that memory directly, but instead use the graphics driver to use that memory. For example (pseudo code):
byte[] image = loadImageFromDisk();
int vramId = graphicsDriver.allocateMemory(image.length);
graphicsDriver.copyToVRAM(vramId, image);
image = null;
...
// At this point the garbage collector will release the memory used by "image".
// However, the allocated VRAM still contains a copy of the image, so you can still use it.
...
graphicDriver.showImageOnScreen(vramId);
...
// The garbage collector can't free the VRAM though, you need to manually free that memory.
...
graphicsDriver.releaseMemory(vramId);
So, practically, there are two kind of resources in this case.
Resources that will be automatically released by the garbage collector. Let's call those: managed resources.
Resources that can't be automatically released by the garbage collector. Let's call those: native resources.
As you probably can imagine, libgdx uses quite alot of native resources behind the scenes. To properly manage those resources libgdx contains the Disposable interface. Every class that implements this Disposable interface uses (directly or indirectly) native resources that can't be released automatically by the garbage collector. Therefor you need to manually call the dispose methods on those classes if you no longer need them.
Not calling the dispose method can potentially result into problems with native resources. E.g. you might run out of available video memory or alike, causing your application to crash or alike. This is most commonly referred to as a "memory leak".
I have an LRUCache that I use to cache thumbnails and other such small bitmaps. Currently, I'm using it in my main activity, however, I'd like to use it my other activities too. This makes me wonder if it's a good idea to simply store this LRUCache object in my custom application singleton (which extends Application) and solve the problem of accessing the cache in other activities. The reason why I'm concerned is because, as I understand it, if the application process is killed - which is very likely to happen when the app is left running for too long in background - the application object and therefore the cache will get garbage collected. Correct me if I'm wrong on that and help me understand this issue better/provide a solution to this problem.
My usual rule of thumb is, for persisted data use disk cache & for quick, dirty & light data, use memory cache (or your lru cache). Be careful with storing bitmaps in memory cache, at least for android devices < 2.3.3, I believe. The pixel data of the bitmap is actually stored in native memory so developers have less control to encourage garbage collections for it. For example, even setting your bitmap to null or invoking the recycle() method may not fully convince the garbage collector to free the bitmap in the dalvik heap (vm heap) since its a small object on the dalvik heap (vm heap), even though it's native counterpart in native memory is large cause OutOfMemoryException.
Sorry for straying off a bit but thought you should know. As for your the answer, your assumption is right. When android is running low on memory it retains the last user activity instance in it's system memory but may kill your process, where your process hosts your application object. So in your case, if you stored 5 bitmap objects in your application object, and users left for sometime, they may come back to an activity requesting a bitmap from a newly created application object by the system, which would then produce a null bitmap.
Given these circumstances the solution is typically clear. If you want to persist data, you can't trust object memory (in-memory, RAM), at least on Android, so disk memory might be your best option.
Hope this helps.
I think this is a perfectly fine idea. Here's a video from Google I/O 2012 with some relevant information: http://www.youtube.com/watch?v=gbQb1PVjfqM
I don't want to create a vague question so I will try to make this as clear as possible (Going to try my best).
I know garbage collection has been a grey area in programming for a very long time. I am not certain with the case of android or other mobile phones.
What I know of garbage collection in android:
It collects class system class ojbects(Made by correction from an answer).
Edit* "GC collects activity items only once the activity is destroyed. Activity lifecycle is driven by its attributes in the manifest, also by the flags of the intent that that launched it." – Seva Alekseyev . As commenter said.
You may force a garbage collection using "System.gc()" although this is not recommended as it may delete something important class item.
Now I obtained this information from stackoverflow(Now knowing that it is no longer a grey area for garbage collection)
Going to my question:
How do you get this information about the process or generic information(book, internet article, etc.) about garbage collection from?
If there is not answer for question 1 what are the other ways or methods that developers should be reminded when developing applications requiring the constant use of memory?
I'm not sure your information is correct.
It collects class system classes.
No. It collects instances of objects that are no longer reachable from any of the system roots. System roots include any static reference, any reference from a thread's active stack frame, any active synchronization monitor, and anything held by a native piece of code (global or local). An object is considered live (and hence cannot be reclaimed) if there is a path from it to a root tracing the reference graph backwards. Any object that doesn't not have a path to a root can be reclaimed by the garbage collector. Classes are referenced by a ClassLoader and are never reloaded and hence are not reclaimed by the system unless that ClassLoader is collected and all instances of those classes are collected. So Android never collects class system classes because that ClassLoader is never collected.
It collects items from activity "only" if android manifest file states that the activity is either hasNoHistory or singleTop
No. An activity is nothing more than an instance of an object. And when the reference to the activity is gone so goes all of the references it pointed to unless some other root points to that object. By setting singleTop="true" you are only telling Android to instantiate a single instance of this activity, and all intents sent will be handle by that single instance. It doesn't have any impact on GC. When an activity looses its path to a root it will be reclaimed regardless of what the settings on that activity were.
You may force a garbage collection using "System.gc()" although this is not recommended as it may delete something important class item.
No Garbage collection algorithms do not delete any live object. Under your definition above it implies GC can collect an object you were using which is incorrect. If it did that's a big bug. That is also the beauty of Garbage Collection algorithms in that they are guaranteed to clean up garbage perfectly. If you are running out of memory the programmer has forgotten to remove a reference or you are being careless with your use of memory. The reason you aren't suppose to call System.gc() is that you/your program has no clue when the best time is to reclaim memory. The garbage collector is trying to maximize the ratio of (the time your program runs) vs. (the time it spends collecting garbage). It keeps very detailed statistics and makes estimations about when its a good time to run garbage collection vs simply allocating more memory.
It's like cleaning your house. You can't clean at all times because it makes doing things take longer sometime you have to let it get dirty (Like cooking). However, if you never clean your house it can take all day to clean it. So there is a balance that you must strike between how dirty can it become before cleaning it up takes longer than performing the task.
This is why you shouldn't calculate/guess/force GC in your program because Android has already implemented it for you, and will do a better job than you can ever hope to.
What does this mean for you the developer?
Let Android handle when GC should run.
Clean up references to help the GC know when something can be reclaimed. Be very careful about static references, and never allow a static to hold a reference to an activity, service, etc to one.
Don't allocate lots of small amounts of short lived memory. This will force more GC time to clean up. By allocating memory conservatively you are by definition helping that ratio.
Most of the time GC is very hands off. The only problems developers get into is not establishing boundaries for long living objects vs. UI objects. If a long living objects has a reference back to the UI that's a place you'll have to unregister or else you'll leak memory. It's ok for the UI to hold references to long living objects, but not the other way around.
The real issue with Android is how much you make the garbage collector work. If you keep the amount of memory you are using small then the garbage collector doesn't have big jobs it has to do. That doesn't mean you should reuse objects or create object pools, etc. But, you should be aware of what statements are creating memory, and how long those objects live for.
There are volumes of information on Garbage collection in general and particularly Java's Concurrent Mark and Sweep garbage collector. Android's garbage collector is not as performant, but it's pretty darn good. Most of the time I don't worry about GC unless there is a problem so it's mostly hands off.
And garbage collection isn't a grey area. It's very much well understood, and the industry has expanded the field quite a bit since Java was introduced in 1994.
While developing reasonably complex applications (e.g. accessing external resources such as files, database, network connections) on Android platform is it necessary to handle the Garbage Collection? Or should I let Android take care of GC all the time?
So does Garbage Collector relives an Android programmer from all burden of freeing memory?
If not, then can anybody explain with a practical example why is it so?
In general, GC helps programmers avoid many problems, but it is not a cure-all. As a programmer using a GC'ed system, you have two main things to worry about in terms of the allocation lifecycle:
Dropping references (e.g. setting variables to null) when objects are no longer needed. Failing to do so could result in a memory leak.
Explicitly managing non-memory resources, such as open files. The objects representing these things typically arrange to free up the resources when the objects get GC'ed, but as the programmer you may have a better idea about when the resource is truly unneeded. So, it is in your best interest to (say) explicitly call close() on an InputStream instead of just letting the GC clean it up long after it's no longer needed.
I have a quick performance question: Is it quicker and efficient on memory to use a static singleton database reference or reopen it every time you need to access something?
Thanks for any help,
~Aedon
In Android the databases aren't kept in memory so keeping the reference will be light on your memory, but will use some file locks. Using a singleton would be my first choice, however, if you're using it in a service or a single activity, it doesn't necessarily need to be static.
If you're database instance keeps a reference to a Context, then by all means avoid making it static because it will be a good source of memory leaks.