w3resource logo


Introduction to Java Programming

Garbage Collection in Java

Secondary Nav

Introduction

Memory management is the process of recognizing when allocated objects are no longer needed, de-allocating (freeing) the memory used by such objects, and making it available for subsequent allocations. In some programming languages, memory management is the programmer’s responsibility. The common problem with explicit memory management is space leaks. These leaks occur when memory is allocated and no longer referenced but is not released. An alternate approach to memory management that is now commonly utilized, especially by most modern object-oriented languages, is automatic management by a program called a garbage collector.

Benefit of garbage collection:

Garbage collection relieves programmers from the burden of freeing allocated memory. Knowing when to explicitly free allocated memory can be very tricky. Giving this job to the JVM has several advantages.

A garbage collector is responsible for

  • Allocating memory
  • Ensuring that any referenced objects remain in memory, and
  • Recovering memory used by objects that are no longer reachable from references in executing code.

Garbage-Collection Roots — The Source of All Object Trees

Every object tree must have one or more root objects. As long as the application can reach those roots, the whole tree is reachable.But when are those root objects considered reachable? Special objects called garbage-collection roots (GC roots; see Figure below) are always reachable and so is any object that has a garbage-collection root at its own root.

There are four kinds of GC roots in Java:

java garbage collection image1

  1. Local variables are kept alive by the stack of a thread. This is not a real object virtual reference and thus is not visible. For all intents and purposes, local variables are GC roots.
  2. Active Java threads are always considered live objects and are therefore GC roots. This is especially important for thread local variables.
  3. Static variables are referenced by their classes. This fact makes them de facto GC roots. Classes themselves can be garbage-collected, which would remove all referenced static variables. This is of special importance when we use application servers, OSGi containers or class loaders in general. We will discuss the related problems in the Problem Patterns section.
  4. JNI References are Java objects that the native code has created as part of a JNI call. Objects thus created are treated specially because the JVM does not know if it is being referenced by the native code or not. Such objects represent a very special form of GC root.

Heap Generations for Garbage Collection in Java

Java objects are created in Heap and Heap is divided into three parts or generations for sake of garbage collection in Java, these are called as Young generation, Tenured or Old Generation and Perm Area of the heap.

In a typical application, most objects are very short-lived. On the other hand, some objects last for a very long time and even until the application is terminated. When using generational garbage collection, the heap area is divided into two areas—a young generation and an old generation—that are garbage-collected via separate strategies. Objects are usually created in the young area. Once an object has survived a couple of GC cycles it is tenured to the old generation.

New Generation is further divided into three parts known as Eden space, Survivor 1 and Survivor 2 space. When an object first created in heap its gets created in new generation inside Eden space and after subsequent Minor Garbage collection if object survives its gets moved to

survivor 1 and then Survivor 2 before Major Garbage collection moved that object to Old or tenured generation.

Permanent generation of Heap or Perm Area of Heap is somewhat special and it is used to store Metadata related to classes and method in JVM, it also hosts String pool provided by JVM.

java garbage collection image2

Full GC and Concurrent Garbage Collection in Java

The concurrent garbage collector in java uses a single garbage collector thread that runs concurrently with the application threads with the goal of completing the collection of the tenured generation before it becomes full. In normal operation, the concurrent garbage collector is able to do most of its work with the application threads still running, so only brief pauses are seen by the application threads. As a fall back if the concurrent garbage collector is unable to finish before the tenured generation fills up, the application is paused and the collection is completed with all the application threads stopped. Such Collections with the application stopped are referred as full garbage collections or full GC and are a sign that some adjustments need to be made to the concurrent collection parameters. Always try to avoid or minimize full garbage collection or Full GC because it affects the performance of Java application. When you work in finance domain for the electronic trading platform and with high volume low latency systems performance of java application becomes extremely critical and you definitely like to avoid full GC during the trading period.

An Example of garbage collection and memory management using Java code. In below code, we are checking memory size before the creation of an array of 10000 string, after the creation of it, after initialization and after de-allocation of all objects. Memory utilization is printed after each stage.

Java Code: Go to the editor

public class MemoryDemo {
	public static void main(String[] args) throws InterruptedException {
		Runtime r = Runtime.getRuntime();
		long mem1, mem2;
		String someints[] = new String[10000];
		System.out.println("Total memory is: " + r.totalMemory());
		mem1 = r.freeMemory();
		System.out.println("Initial free memory: " + mem1);
		r.gc();
		mem1 = r.freeMemory();
		System.out.println("Free memory after garbage collection: " + mem1);
		for (int i = 0; i < 10000; i++)
			someints[i] = i+""; // allocate integers
		mem2 = r.freeMemory();
		System.out.println("Free memory after allocation: " + mem2);
		System.out.println("Memory used by allocation: " + (mem1 - mem2));
		// discard Integers
		for (int i = 0; i < 10000; i++)
			someints[i] = null;
		r.gc(); // request garbage collection
		Thread.sleep(100);
		mem2 = r.freeMemory();
		System.out.println("Free memory after collecting discarded String: " + mem2);
	}
}

Output:

(your output may very as per JVM and OS version)

java garbage collection image3

Summary

  • Java Heap is divided into three generation for sake of garbage collection. These are young generation, tenured or old generation, and Perm area.
  • New objects are created into a young generation and subsequently moved to the old generation.
  • String pool is created in Perm area of Heap, garbage collection can occur in perm space but depends on upon JVM to JVM.
  • Minor garbage collection is used to move an object from Eden space to Survivor 1 and Survivor 2 space and Major collection is used to move an object from young to tenured generation.
  • Whenever Major garbage collection occurs application threads stops during that period which will reduce application’s performance and throughput.
  • There is few performance improvement has been applied in garbage collection in java 6 and we usually use JRE 1.6.20 for running our application.
  • JVM command line options –Xmx and -Xms is used to setup starting and max size for Java Heap. Ideal ratio of this parameter is either 1:1 or 1:1.5 based on my experience, for example, you can have either both –Xmx and –Xms as 1GB or –Xms 1.2 GB and 1.8 GB.
  • There is no manual way of doing garbage collection in Java

Java Code Editor:







Join our Question Answer community to learn and share your programming knowledge.