Android proper clean up/disposing - java

Is there a way to "clean up" objects and other variables you create? Or are they automatically disposed of or do I have this whole concept wrong? What is the proper way to go about doing this? I am trying to avoid the GC as much as possible.

The only way to cleanup in an GC language with no memory management is the GC . You can force GC but its not recommended , the GC is pretty good , to be more proactive set objects to null for the GC to clean up.
Addition:
Also try to make objects as local as possible , that way they are GCed as they scope out.

Calling System.gc() will force Garbage Collection to happen.
There is a system counting references to objects you create. If you are looping a lot and creating lots of objects you will create periods of time where they pile up. The system will collect the garbage when your processor is not doing anything, or it will wait till you need more free memory before collection occurs. If you have been processing for some time, you will experience hiccups in your performance due to Garbage Collection happening during your processes.
Please view this page and search for "Garbage Collection"
http://developer.android.com/guide/practices/design/performance.html
NOTE: Anything created with an Application Context will live until the end of the application execution. Anything created with an Activity Context will live until the end of the activity. This two situations can cause memory leaks!

For a more complete answer specific to Android:
Make sure you review the application lifecycle for android. It will help you avoid activity leaks in Android.

For the most part they are cleaned up as long as you do not maintain a reference to the object (variable). Something's like cursor's and bitmap's though need to be closed before they can be deleted to prevent memory leaks.
I don't think you have to worry about the GC as long as your object creation is not over the top. Note: GC is a part of java. You can't avoid it.
Addendum 1: If you really are that worried about it, you could reuse variables. That way you keep object creation to a minimum, but in so doing you will lose that variable and will be unable to store a wide range of data.

Android's activities have onDestroy() method. You can use this method to close open connections or dialogs or close some pending tasks.
You could also read about Java GC to get a more proper understanding of it. I would recommend SCJP book, Garbage collection chapter. It explains well when an object becomes eligible for garbage collection.

Related

Garbage collection loading screen

I have two activities in my android application. When I switch from first activity to second activity, gc starts and makes second activity to lag until it completes. I decided to make a splash screen (loading screen) that will not close until gc finishes but I do not know how to get gc status pro-grammatically. Is there any class of it? Please let me know how can I get this scenario!
To begin with, in Android, garbage collection is organized by the ART - Android Runtime or DVM - Dalvik Virtual Machine (on older devices). As ART/Dalvik are essentially specialized versions of JVM, they have similar approach to GC, hence it is solely managed by the system and not by the user.
Hence, you don't get to control the garbage collection in Android.
Indeed, you can call System.gc(), but it's nor guaranteed nor recommended to do. You are expected to completely forget about garbage collection process and leave it to the system.
While you cannot control it, you are still responsible to manage the memory and prevent excessive memory usage as much as possible. A few tips, you should consider:
Release bulky objects (remove hard references pointing to them) as soon as you're done working with them;
Utilize multithreading to your needs, threads will work in parallel and faster (especially on multi-core processors);
Optimize your algorithms, even basic list iterations could potentially slow the process and leak memory if done incorrectly
Thank you guys for answers. After some working i found what the problem in code.
I was executing this async class in while loop with new instance. So it keeps memory increasing and after two hours it starts hangs or when activity switched gc executes.
I think the answer by #Serj sums it up quite good. Maybe you find a workaround to get the GC triggered if you keep the instance of your old activity, and thus have it still being referenced, until your splash screen is set up. Then you remove the last references and hope for the GC to be called - but yet it could happen that it will get called later. It's a good question how to see the status of the GC, maybe you can read out the memory and see if its filled or not?
The best advice is refactoring and using objects only in scopes in which they are needed.

How to keep some data as long as possible, but allow the VM to free & reload them at need?

In my application, I would like to load some amount of data into memory when first needed and keep it there in case another part of the application wants to use it. The same data would be accessed from a couple of different Activity'es, but by far not all the user could interact with. So, when not working with the relevant part of my application, I would like Android to feel free to discard the data, reloading them again at need. Note that it is unpredictable for me what the user will do, so I want Android to free the data only if hasn't been used for some time. What is a good approach to doing this?
I thought of creating a class that would be only used statically, loading the data in its static initialisation block. However, I am not sure if Dalvik would ever discard any static data stored this way. I have read something on class loaders but I have no idea what loader is used in loading my class and how it could potentially become discarded. Perhaps someone does...?
Another way I came up with is using weak reference to keep an instance of the data-holding class (non-static, obviously) but here I am afraid that the GC could decide it's useless when no Activity is currently actively operating it, even when memory is no concern at that moment. (In that case, I would like to keep the data loaded.)
The loading of my data is costly. I want, if possible, to destroy it only when the system is running out of memory or when the application exits.
It sounds like SoftReferences are what you need. These are cleared at the garbage collector's discretion when it detects that there is a memory shortfall.
If you read the class javadoc, it gives some hints about how to prevent recently used cache entries from being reclaimed.
For the record, classloaders won't help you manage instances of a class. But making the cache a static should allow the cached objects to be discarded if the cache class gets unloaded.
FOLLOWUP
My data is a solid block that would be represented by a single object.
This rather changes things. If you have a single object to cache, then LRU makes no sense. Basically it sounds like you want to hang onto the object as long as possible ... without trigger OOMEs by hanging onto it too long. This is kind of hard. Indeed, doing a perfect job is going to entail correctly predicting what the user is going to do ... which is clearly impossible.
Possibly the best strategy is to make use of the reference enqueing mechanism, and implement the queue processor to make an "intelligent" choice between letting the object die or recreating the soft link. The "intelligence" might entail looking at how much free memory there is, and / or how long it was since the object was last used. But beware!! If you get this wrong you can cause OOMEs or cause the platform to spend lots of time thrashing the garbage collector.
If I set up the cache to hold 1 object, it would be equivalent to a hard reference, wouldn't it?
Nope. If you use a SoftReference the GC will break the reference if it is running out of memory.
You can use SoftReferences. Take a look at:
http://docs.oracle.com/javase/6/docs/api/java/lang/ref/SoftReference.html
With SoftReferences you can achieve what you need:
" I want, if possible, to destroy it only when the system is running out of memory or when the application exits."
Take a look at
SoftReference gets garbage collected too early
You can also look into LruCache if your looking to cache some data in memory your app.
http://developer.android.com/reference/android/support/v4/util/LruCache.html
For a longer lived disk based cache take a look at Android Objects Cache
You can find the DiskLruCache source at https://github.com/JakeWharton/DiskLruCache/

How does the GC know when to collect an object?

I know that the GC collects objects that have no references pointing to the object in question, but what happens in the event of listener objects?
Suppose you have an AnimationDelegate that listens to data from a DataSupplier. When the DataSupplier recieves data and fires off the event to the AnimationDelegate, the delegate will then invalidate (/update/redraw etc...) a Graphic. Now say the screen is disabled, removed or, through various means, the graphic can no longer draw and is collected. The AnimationDelegate is still registered to the DataSupplier. How will the GC know to collect it? Should one unregister the delegate in the graphics finalize() method?
I'm afraid the answer won't fit the format :) Start with this article by Brian Goetz: he's a perfect person to read if you're interested in GC.
Basically, as soon as object is not reachable from active threads, it's collected. The actual algorithms vary even within one JVM, but the point stays the same: what's not reachable is a garbage. What's reachable is not a garbage. Easy.
GC will not collect the Graphic in your example, as it's reachable from AnimationDelegate, which in turn is reachable (via subscription) from DataSupplier which is supposed to be reachable from some active thread. So the answer will be: your assumptions are wrong; GC will not collect anything here.
To answer your question, unsubscribe everything you don't need.
As #rfeak rightfully says, finalize() is a big no-no. It's almost impossible to use it properly, and it's way too easy to use it wrong. That said,it's OK to use it as a backup solution when you need to free resources. But generally your application has to be able to work just fine even if finalize() never gets called.
It all depends on the JVM you're using and the GC. Most default GC from the JDK use the so called "tracing collectors", which simply start at a given root set of objects and trace all the objects reachable from that set. All the other objects in memory are seen as garbage and deleted. So circular references aren't really a problem unless one of the objects is reachable from the root set.
What is the root set of objects? Well if memory serves right roots can be found in: program registers, local variables in each thread's stack and static variables.
To see if your objects will be GC'd we would know more about the design of your application.
#Edit: Oh and I almost forgot: Memory Management in the JavaHotSpotâ„¢ Virtual Machine. This is a pretty good overview of how it all works.
It will only know if you have removed the references (nulled them out).
However, don't do this on finalize(). Finalize is bad bad bad. There should be other lifecycle methods available for cleaning up listener(observer) type objects.
By the way, observer pattern is notorious for creating memory leaks because the GC couldn't collect due to lingering references.

Java Memory Leaks

I'm creating a service that will run constantly, each day at a specified time it will run the main body of the program.
Essentially:
while(true){
run();
Thread.sleep(day);
}
After a while, I'm getting OutOfMemoryHeapExceptions.
After reading about this a little I'm thinking its because any objects created inside the run() method will never be garbage collected.
Therefore I have done something like:
public void run(){
Object a = new Object();
a.doSomething();
a= null; //Wasn't here before
}
My question is, will this solve my problem? I'm under the impression that once an object is null, the object it previously referenced will be garbage collected? Also is this a good idea? Or should I look at doing something else?
Thanks
Adding a = null will almost certainly be insufficient to fix the problem (since a is about to go out of scope anyway).
My advice would be to use a memory profiler to pinpoint what's leaking and where.
I personally use YourKit. It's very good, but costs money (you can get a free evaluation).
Another recently-released tool is Plumbr. I am yet to try it, but the blurb says:
Try out our Java agent for timely discovery of memory leaks. We'll tell you what is leaking, where the leak originates from and where the leaked objects currently reside - well before the OutOfMemoryError!
That might indeed help, in some circumstances the GC algorithm needs a little help to perform, but it doesn't guarantee to solve your problems, merely delay them.
My advice:
Simulate the same behavior with a lower time period, so you can force the error to happen.
Run it with a profiler and see where all that memory is going, and work from there.
Your impression is incorrect. Objects created inside the run() method will be garbage collected provided they 1) go out of scope, and 2)have released any native or remote system resources they are using.
What functionality are you actually performing inside your run() method call? Are you reading files, making database calls, writing to sockets? Without knowing the details its very difficult to provide a better suggestion.
No. You don't need to set the variable to null. The VM knows that you exit that scope and that the variable a no longer exists, so it automatically decrements the reference count and your object is elegible for garbage collection if it had no other references.
The error is somewhere else.
Setting references to null depends if your object is still in scope in a long time consuming process, though theoretically it will mark the reference as null you cannot guarantee when it will be garbage collected.
You need to check if your objects are being held in long scope somewhere in your code.
Found a nice explanation of setting references to null : Does setting Java objects to null do anything anymore?
In order to corner out your issue you need to profile your application.
Searching SO gave so many pointers on Garbage Collection that I have decided to just place the search string here:
https://stackoverflow.com/search?q=Java+Garbage+collection+and+setting+references+to+null
http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html
Local variables should be collected by GC. So, you don't need to put obj=null;. Because Object is also stored in Heap area.
You should get a memory dump and analyze that using tools like JConsole JVisualVM.
The scope of the run() method is left before the Thread.sleep(day); and thus any variables inside that method are destroyed. After that a won't exist any more and thus the object referenced by that variable might be eligible for garbage collection provided there's no other reference to it.
Analyzing a memory dump should allow you to find any references to those object if they still exist.
It might as well not be those objects but others that are kept alive and which eat up the memory. That depends on what you're actually doing and might be hard to analyze here. Thus look out for huge object graphs in terms of memory usage.
For instance, we had a problem with database connections that were created frequently (XA recovery mechanism) and we thought they'd be destroyed once the method scope is left. However, the server put those connections into a static list and never cleared it and thus we ended up with no memory really soon. What helped us identify that case was analyzing a memory dump. :)
In the short term a pragmatic approach to keeping your application stable is to exit the JVM after each execution. Use a batch scheduler (e.g. cron on *nix, at on Windows) to execute your application just once every day. Any memory leaks will be cleaned up when the JVM exists for sure. However you may have to be careful you're not leaving database connections open, etc.
This will give you time to troubleshoot and fix the underlying memory leak issues while keeping your production code running and not requiring support staff to restart servers, etc.
I'm assuming you're not running out of memory on a single execution

Avoiding multiple Garbage Collection execution

Read in some blog that GC in Android happens on main(UI) thread, this may create sluggishness in UI screen depending on the frequency of GC execution.
Hence I was wondering will it be a good idea if I manually release objects(by assigning null value) which has no further use for me.
This way we may avoid multiple execution of GC in the application.
Please share your thoughts.
Thanks,
sku
There's no such thing as "manually releasing objects" -- at least not in any way that's meaningful to GC. An object doesn't immediately get freed/collected/whatever when you lose all references to it; it just becomes eligible for collection. GC is what actually does the releasing of the object, and it does so when it feels like doing so.
The only real way to keep the GC from working so hard is to create fewer objects, particularly temporary objects. Less garbage == less collection.
Releasing (dereferencing) objects for which you have no further use is always a good idea. You can also use SoftReference, WeakReference and/or WeakHashMap to help the GC pick up stuff that you don't mind going away if the system needs space.
There's more information about Android's GC system here.

Categories

Resources