tags:

views:

63

answers:

4

Hi,

Below is the code snippet to examine the memory

public class TestFreeMemory {

    public static void main(String ... args){

        Runtime rt = Runtime.getRuntime();
        System.out.println("Free Memory (Before GC): " + rt.freeMemory());

        rt.gc();
        System.out.println("Free Memory (After GC1): " + rt.freeMemory());

        rt.gc(); // Second time to ensure results are consistent 
                 // MAY BE has collected all non-reachable objects
        System.out.println("Free Memory (After GC2): " + rt.freeMemory());

        String s = new String("abcd");
        Integer i = new Integer(12345);
        System.out.println("Free Memory (After String Creation): " + rt.freeMemory());
        // Why is freeMemory not reflecting the memory consumed by two objects
    }

}

and the output is

Free Memory (Before GC): 1859672
Free Memory (After GC1): 1911768
Free Memory (After GC2): 1911768
Free Memory (After String Creation): 1911768

Why is freeMemory not reflecting the memory consumed by two objects ?


To be more clear, the question is about getMemory() call not showing up expected result even though two objects are created and not related to GC. Two GC calls are made just to try to make sure the numbers of getMemory() call are correct.. and BTW, there's no GC call after objects are created.. so pls Note that i am not trying for a GC after objects are created ..

A: 

The GC does not free memory when you call it, but when more memory is needed.

thelost
+3  A: 

Memory Management on HotSpot JVM:

Another desirable garbage collector characteristic is the limitation of fragmentation. When the memory for garbage objects is freed, the free space may appear in small chunks in various areas such that there might not be enough space in any one contiguous area to be used for allocation of a large object. One approach to eliminating fragmentation is called compaction, discussed among the various garbage collector design choices below.

Memory Management in HotSpot JVM (PDF Format).

This behavior can be very dependent on the particular implementation of the garbage collection. For example:

Parallel Mark Compact

  • Stop-the-world
  • Heap divided into fixed-size chunks (> 2kb now, will likely increase or be subject to ergonomics)
  • Chunk is unit of live data summarization
  • Parallel mark
  • Record live data addresses in external bitmap
  • Find per chunk live data size
  • Find dense chunks, i.e., ones that are (almost) full of live objects

I've made this sample (with abusive String concatenation to use up more memory):

public class TestFreeMemory {

 static void allocateSomeMemory(){
  long[][] array = new long[400][400];
 }

    public static void main(String ... args){

        Runtime rt = Runtime.getRuntime();

        allocateSomeMemory(); // once we leave, our array is not reachable anymore 
        System.out.println("Free Memory (Before GC): " + rt.freeMemory());     
        rt.gc();
        System.out.println("Free Memory (After GC): " + rt.freeMemory());

        String a = new String("A");
        for(int i = 0; i < 100; i++){
         a+="B";
        }

        System.out.println("Free Memory (After String Creation): " + rt.freeMemory());
        // Less free memory expected.
    }

}

Output:

Free Memory (Before GC): 3751800

Free Memory (After GC): 5036104

Free Memory (After String Creation): 5012048


If I use a relatively small number of iterations in the loop (say 10), the extra space does not show up in freeMemory(), and I'd get something like this:

Free Memory (Before GC): 3751800

Free Memory (After GC): 5036040

Free Memory (After String Creation): 5036040

Bakkal
@Bakkal - Thanks for pointer to **Excellent** doc ... accepted as answered ...
JWhiz
+1  A: 

It's a good question since you are expecting an INCREASE in memory usage to be reflected it seems a logical test. You can assume this behaviour is because the Heap management and garbage collection system is somewhat more complex that a simple Free vs Allocated boundary. Allocation is probably done in chunks much bigger than your one String + one Integer and so free memory is likely to be counted by summing up free chunks.

jowierun
A: 

Try to allocate more memory and you will see an increase. I guess java preallocates at least enough bytes (how smart!) to hold your strings OR they were in the string pool already.

atamanroman