Consider two examples below. In option (1.), after I call arrayList.clear(), I know the API says that "The list will be empty after this call returns." But what happen if I have a huge ArrayList then I do "clear()". The list will be empty but how about memory allocated to the ArrayList. Will it be allocated back to the O.S. like option (2.) does?
Originally posted by Susan Smith:
I see. So it seems that arrayList.clear() is prone to memory leak.
No. All the objects that were in the list have become aligible for garbage collection. The list itself is not eligible for garbage collection because you still have a reference to it. If that reference were to go out of scope then the list could also be garbage collected.
It's only as prone to memory leakage as any other object that you keep a reference to.
1.) I create a new list with 100 items. The list now has 100 object pointers. Each pointer in the list reference to an object somewhere in memory.
2.) Then I call clear(); Now all the objects referenced by the pointer in the list have become eligible for garbage collection. But the list itself still uses memory to keep 100 object pointers.
3.) Then if I fill in the list with 5 more items. Then I have a list with 5 items but the memory size used by the list is stil for 100 object pointers.
Is this correct?
Originally posted by Andre Brito:
...Then, that ArrayList is for the GC (a), right?
Yes, that is true. The arraylist object being referenced by the 'a' becomes eligible for GC.
The same holds good for the option (2) suggested by OP. As soon as you assign a new arraylist to the reference variable as an alternative to clear(), the earlier arraylist being referneced by this reference variable becomes eligible for GC until there are no active references to it.
Thanks for your reply.
Susan - that's correct. At least for the current implementation of ArrayList, and I think it's always been true. You can use the trimToSize() method to fix this if you like. It's not exactly a memory leak in the traditional sense - it doesn't keep growing. But whatever was the maximum size ever used by the ArrayList (for valid non-memory-leak reasons), that maximum size will be retained even when it's no longer necessary.
Can someone please recommend how do I prove this? I might need to show some proofs to my coworker to ensure them that this is what happen.
If your co-worker is obstinate or unable/unwilling to follow the code in ArrayList.java, you could write a demo program. Create an ArrayList, and print the value of Runtime.freeMemory(). Then add 100000000 null entries to the list, and print the free memory again. Then call list.clear() and System.gc() - heck, call gc() ten times in a row to give the memory a really good scrubbing - and print the free memory again. you should see that the memory usage has not gone back to normal; it's still taken up by that huge empty ArrayList. Then replace the ArrayList with a new ArrayList(), run gc(), and print the free memory. You should see a big difference.
I wrote some code and it shows that "new ArrayList()" frees up memory a lot. But there is one part that I don't understand from the result. "Free Memory (after adding pointer)" seems to be bigger than the initial "Free Memory (Initial)"
And the result is below:
Free Memory (initial):1198296
Free Memory (after adding pointer):132967888
Free Memory (after clear()):494980672
Free Memory (after new ArrayList()):1016721528
Press any key to continue...
The last column is the one you care about, but the other columns may help you understand what's going on.