Tuesday, December 13, 2011

Memory Management in Java : Garbage Collector

Java Garbage Collector is responsible to sweep all the garbage objects remains in memory and leave only those objects which are still referenced on the memory stack. For this, JVM uses 'Mark-Sweep-Compact' three phase techniques. Here JVM give three passes to memory objects to destroy the garbage objects. The process is 

  • In first pass, GC traverses on the Memory Stack and mark all the objects which are referenced from Memory Stack through any scope data structure. 
  • In second pass, GC claims the space of all unmarked objects to release their memory. Before claiming the objects for collection, the demon thread, Garbage Collector, call 'finalize' method of the object in order to give it a chance to do the resource cleanup. Here if any object resurrect it again, i.e. do some activity which put its memory reference back to Memory Stack, garbage collector won't collect its memory and leave this. However in this process, GC maintains a state for the objects for which 'finalize' method has already been called once. In next garbage collection cycle, it does not call the 'finalize' method on this object. 
  • In third pass, garbage collector compact the memory space which was released by second pass and hence made the released memory available for JVM. 

This way, GC manages the memory. The process followed to manage the memory is not light in its processing, as three phases process takes a lot of time to execute and hence is a heavy process. Due to this, JVM does not call the GC very often, but it calls it only when it really feels that memory is low and program may need more memory soon. So even if you are calling System.gc(), it does not mean that JVM will call the GC. However it is just like a request to JVM to consider calling the GC. But JVM has its internal logic to decide when to call the GC. 

 

'Finalize' method is used for resource cleaning process by most of the applications. You can use this method to release any resource like ObjectOutputStream, any handle to an OS file etc. But be very careful while relying on this method. Reason is that JVM does not guarantee to call the finalize method. Consider a condition, when program never face a memory pressure and hence JVM never finds the need to call the GC.  



--
Amit Ranjan
Java developer
............................

Thursday, December 8, 2011

How much memory the java objects consume?

For an empty class:

public class TestClass {

}

size of the TestClass Object is 2 * Reference = 2*4 = 8 bytes.

For a class with primitive – int:

public class TestClass {
int i=0;
}

size = 2 * reference + size of int = 2*4 + 4 = 12 = 16 bytes (word aligned)

For a class with primitive – long:
public class TestClass {
long i=0;
}

size = 2 * reference + size of long= 2*4 + 8 = 16 bytes.

similarly for float and double , the size is 16 bytes.

Taking the wrapper classes,

public class TestClass {
Integer i= new Integer(0);
}
size = 2 * reference for TestClass Object + 2*Reference for Integer
object + size of int

= 2*4 + 2*4 + 4 = 32 bytes (word aligned)

Similarly the sizes for the objects with the Long, Float and Double
fields are32 bytes.

Instead of using the 'new' key word for the Integer instantiation, if
we use Integer i=1; then the results are different.

public class TestClass {
Integer i=0;
}

size = 5152 bytes.

The reason being Integer i=0; is inferred as Integer i= Integer.value(0);

A cache is initialized with all the possible int values varying from
-128 to 127. The 'i' is initialized with the value zero from the
cache.

If you take the String instantiation,

public class TestClass {
String s=new String("i");
}

it consumes about 40 bytes of memory where as,

public class TestClass {
String s="i";
}

consumes about 16 bytes of memory. It took less bytes since "i" is
from the string pool.