views:

88

answers:

3

Hi guys, I just wanted to know what happens behind my program when I declare and initialize a variable and later initialize it again with other values, e.g. an ArrayList or something similar.

What happens in my RAM, when I say e.g. this:

ArrayList<String> al = new ArrayList<String>();
...add values, work with it and so on....

al = new ArrayList<String>();

So is my first ArrayList held in RAM or will the second ArrayList be stored on the same position where the first one has been before? Or will it just change the reference of "al"?

If it is not replaced...is there a way to manually free the RAM which was occupied by the first arraylist? (without waiting for the garbage collector) Would it help to set it first =null?

Nice greetings, poeschlorn

+1  A: 

New space in the Heap will be allocated for the new ArrayList.

You can not force garbage collection and assigning null will only serve to eat up processor cycles. You can call System.gc() to suggest the JVM run the garbage collector, but there are no guarantees.

Tim Bender
IIRC, on Sun's JVM the System.gc() call will always force a full GC, which is much slower than just collecting the young generation.
Esko Luontola
@Esko, I believe you are right, but strictly speaking, you can't make assumptions about the JVM implementation. The OP asked for a manual way, System.gc() is the "manual way".
Tim Bender
+4  A: 

The new ArrayList will be allocated from some different part of the memory, the reference is changed to point to it, and if the old ArrayList is not anymore referred by something else, it will be garbage collected. There is no way to manually free memory in Java. It happens automatically.

Settings variables to null is irrelevant, when it is set to something else right after that or it's a local variable which anyways gets out of scope soon (but inside data structures like ArrayList, setting elements of the contained array to null, when the element is removed, is required to avoid memory leaks).

Esko Luontola
+4  A: 

The code you post will allocate a new ArrayList instance. If you want to reuse the same one, you can do this:

ArrayList<String> al = new ArrayList<String>();
...add values, work with it and so on....

al.clear();
// now you can use a1

But do this with caution - if you pass the initial instance of a1 to other code that will be using it for a longer period, then clearing it will cause problems and you will need a separate instance.

But also note that the savings you get from recycling object arrays and ArrayLists aren't that great. If you were storing 10 x 4096 byte strings in the ArrayList, the array list itself only occupies space proportional to the size of the references, e.g. circa 4 bytes x 10 = 40 bytes. This is a simplification, but the principle is correct. So, even if you reuse the same array list, you are only saving yourself the memory used to store the object references, not the objects themselves. With that in mind, and the risks of causing bugs by modifying a collection unintentionally, I would guess most people don't bother recycling lists.

The memory management in a modern VM is really very good, and you should only start introducing memory "optimizations" when you see that there is a need for it. In fact, using objects for longer than their natural lifetime can have a negative effect on garbage collection performance.

My advice is, code it clearly first, profile, and only focus on optimizing memory use when you see there is a problem and have identified the cause.

Good luck!

mdma
+1: Early optimization is the ...
DR
It's also important to note, that calling ArrayList.clear() is not free either, because it will set all elements of the contained array to null (though it's an implementation detail). It can easily be faster to allocate a new ArrayList than to clear the elements of the old array. But things like these must be profiled, to find out which is faster - premature optimization is the...
Esko Luontola
... evil stepchild of micro-benchmarking?
mdma