I'm testing how gc works with the classes in java.lang.ref package, just for study :)
The following is my code.
public static void main(String [] args) {
int mb = 1024*1024;
//Getting the runtime reference from system
Runtime runtime = Runtime.getRuntime();
System.out.println("##### Heap utilization statistics [MB] #####");
ArrayList<Object> sb = new ArrayList<Object>();
for(int i =0; i < 5000000; i++){
sb.add(new Object());
if( i % 1000 == 0) {
System.out.println(i);
}
}
SoftReference<ArrayList> wr = new SoftReference<ArrayList>(sb);
// System.gc()
//Print used memory
System.out.println("Used Memory:"
+ (runtime.totalMemory() - runtime.freeMemory()) / mb);
//Print free memory
System.out.println("Free Memory:"
+ runtime.freeMemory() / mb);
//Print total available memory
System.out.println("Total Memory:" + runtime.totalMemory() / mb);
//Print Maximum available memory
System.out.println("Max Memory:" + runtime.maxMemory() / mb);
}
It results:
Used Memory:95,
Free Memory:28,
Total Memory:123,
Max Memory:247
And I undid comment on "System.gc()", and reran the code, the result was
Used Memory:1,
Free Memory:122,
Total Memory:123,
Max Memory:247
Yeah, firstly, the instance of ArrayList was collected. As I know, Instances referenced only by SoftReference is softreachable, so collected when GC is really needed because of lack of left heap space. The left space of first result of the code was about 150(free mem 28 + left max mem 124). I don't understand why the instance of ArrayList was collected.
And secondly, I ran the code with modifying:
sb.add(new Object()); -> sb.add(new StringBuffer(i));
and It resulted:
Used Memory:245,
Free Memory:2,
Total Memory:247,
Max Memory:247
Why is this different??
And lastly, I ran the code again with modifying: from
SoftReference<ArrayList> wr = new SoftReference<ArrayList>(sb);
to
WeakReference<ArrayList> wr = new WeakReference<ArrayList>(sb);
It resulted:
Used Memory:245,
Free Memory:2,
Total Memory:247,
Max Memory:247
I had guessed the instances of ArrayList were collected because the instances were referenced only by WeakReferece, so these were weakreachable. But they were not collected.
I now assume that my understanding about the way of Reference's work was incorrect.
Please anyone let me know why.
Thx ^^
sbreference itself, theArrayListwould certainly not be collected. Didn't you just remove somesb = null;line between the second and third tests? - Dolda2000ArrayList. If anything, the differences you are seeing are probably due toArrayListresizing itself repeatedly, which allocates progressively larger arrays during your loop. (And those arrays are what is being garbage-collected.) Also, I'm not sure I understand your question aboutStringBuffer.StringBufferis much larger than a plainObjectbecause it has an array inside it. Shouldn't it therefore be expected that it uses significantly more memory? - Radiodefchar[]inside it. - Peter Lawreynew StringBuffer(i)whereiis close to5000000then it is going to use around 10 MB per buffer. Where asnew Object()will use around 16 bytes even for large values ofi. - Peter Lawrey