Home » Core Java » Garbage Collection in Java

About Gilbert Lopez

Gilbert Lopez is an application developer and systems integration developer with experience building business solutions for large and medium-sized companies. He has worked on many Java EE projects. His roles have included lead developer, systems analyst, business analyst and consultant. Gilbert graduated from California State University in Los Angeles with a Bachelor of Science degree in Business.

Garbage Collection in Java

In this article, we will cover garbage collection in Java. We’ll look at the Garbage Collector and discuss the conditions that make an object eligible for collection. We’ll also explore the topics of object reachability and object cleanup. Finally, we’ll show how to call the garbage collector in our code.

1. Introduction

When writing an application, you may need to allocate memory to store data. In some languages, this is done explicitly. In C, for example, you use the malloc function to allocate memory for data structures. In other languages, this is done implicitly. In Java, you use the new operator to create an object. The JVM will then allocate memory to store the object.

But how do we free up memory when it is no longer being used? In C you can de-allocate memory with the free function. Java uses a garbage collector for this task.

2. Garbage Collection in Java

Memory management is an important concern in any application or program. It can help prevent such issues as memory leaks that can cause your application to run out of memory.

Most modern languages, such as Java, use dynamic memory allocation and garbage collection to manage data stored in memory. This is a boon to programmers since allocating and releasing memory can be tedious and error-prone.

Garbage collection in Java is the process of reclaiming memory occupied by objects that are no longer used by the running application. The JVM runs a low priority background thread, called the Garbage Collector, to free up this unused memory.

2.1 The Garbage Collector (GC)

So how, you may ask, does the GC accomplish this task? Garbage collection is generally a two-step process.

  1. The GC identifies the objects that can be reached by a live thread (through a reference) and marks them as live objects. If there are no references to an object, it is considered unreachable and eligible for garbage collection.
  2. Then, at some unspecified juncture, the GC will remove unreferenced objects and reclaim its memory. (Technically, the memory is freed and available to store new objects.)

2.2 Objects Eligible for Garbage Collection

Let’s see a simple example that shows how an object can become eligible for garbage collection.

public class LocalObject {

	public static void main(String[] args) {

		someMethod();
		
		System.exit(0);
	}

	static void someMethod() {
		MyObject myObj = new MyObject();
		System.out.println(myObj.sayHello());
	}

}

class MyObject {
	public String sayHello() {
		return "Hello!";
	}
}

To understand this example, we first need to talk about heap space and stack memory. The heap space is where objects are stored. The stack memory is where method execution occurs. It holds primitive values and references (pointers) to objects in the heap.

During the execution of someMethod, an object of type MyObject is created in the heap and a reference to it (myObj, a local variable) is stored in the stack. When someMethod terminates, the reference to MyObject (myObj) goes out of scope, since it is a local variable. MyObject is now unreachable, making it eligible for garbage collection.

2.3 Reachable Objects

The example above serve to acquire a rudimentary understanding of how garbage collection works but most scenarios are not so clear cut. Applications can create scores of objects that are interrelated. What objects are unreachable in these situations? We can use an object reachability graph to determine this.

Garbage Collection in Java - Object Graph
Object Graph

To better understand this graph, we need to talk about garbage collection roots. A GC root is an object that is accessible from outside the heap space. Examples of GC roots are:

  • System Classloaders
  • System Classes
  • Threads
  • Static Variables

The GC traverses the objects in the graph beginning from the GC roots. Any objects that cannot be reached are dead objects and eligible for garbage collection.

Static variables are GC roots. Let’s look at an example.

public class StaticObject {
	
	static MyObject myObj = new MyObject();

	public static void main(String[] args) {
		someMethod();
		System.out.println("In main - " + myObj.sayHello());

	}

	static void someMethod() {
		System.out.println("In someMethod - " + myObj.sayHello());
	}
}

class MyObject{
	public String sayHello() {
		return "Hello!";
	}
}

Static members (variables and methods) are associated with the class itself and not instances of the class. This means you can access them from anywhere in the application. Static variables are initialized when the class is loaded and before any instances of the class are created. Since they are loaded into the heap space by the classloader with the class, they cannot be garbage collected and remain in memory for the duration of the program. (Note: You should use static variables judiciously for this reason.)

In the example above, an object of type MyObject is created and tied to the static variable myObj when the StaticObject class is loaded into memory by the classloader. MyObject remains in the heap space, even when the program ends since it referenced by a static variable.

2.4 Causing Objects to Become Eligible for GC

As shown in the first example, an object created within a method will become eligible for garbage collection when the method exits, since there is no longer any reference to it. But you can explicitly make an object eligible within a method or constructor. Let’s look at two examples.

public class NullifyObject {

	public static void main(String[] args) {
		MyObject myObj = new MyObject();
		myObj.sayHello();
		myObj = null;
		myObj.sayHello();
	}
}

class MyObject{
	public String sayHello() {
		return "Hello!";
	}
}

When variable myObj is assigned to null, the previously assigned object is no longer reachable and is eligible for CG.

Another way an object can become eligible is through re-initialization.

public class ReinitObject {

	public static void main(String[] args) {
		
		MyObject myObj_A = new MyObject();
		MyObject myObj_B = new MyObject();
		System.out.println(myObj_A.toString());
		System.out.println(myObj_B.toString());

		myObj_A = myObj_B;
		System.out.println(myObj_A.toString());
		System.out.println(myObj_B.toString());
	}

}

class MyObject {
	OtherObject otherObj = new OtherObject();
}

class OtherObject {
	
}

When we reinitialize the variable myObj_A to the object pointed to by myObj_B, the original object is no longer reachable and therefore eligible for GC. Also, note that any instance variable referenced objects of the original object (e.g OtherObject) are also no longer reachable and eligible for collection.

2.5 Cleaning Up

If you are writing a class that uses resources, you will want to release those resources before the object is garbage collected. The finalize method from the java.lang.Object class was sometimes used for this purpose but there are many problems associated with its use and it has been deprecated.

One option for cleaning up your object before it is destroyed is to have your class implement the AutoCloseable interface and use it in conjunction with a try-with-resources block.

ShowFile.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class ShowFile implements AutoCloseable {
	
	BufferedReader inputStream;

	public String returnContentsOfFile() throws IOException {
		inputStream = new BufferedReader(
			new FileReader(getFile("quote.txt")));
		StringBuffer output = new StringBuffer();
		String line;
		while ((line = inputStream.readLine()) != null) {
			output.append(line + "\n");
		}
		return output.toString();
	}
	
	private File getFile(String fileName) {
		return new File(
			this.getClass()
			.getClassLoader()
			.getResource(fileName)
			.getFile());
	}
	
	@Override
	public void close() throws Exception {
		System.out.println("Cleaning up resources...");
		inputStream.close();
	}

}

The AutoCloseable interface has one method, close. This method is automatically called, regardless of whether the try statement ends normally or in an exception.

ShowFileDriver.java
public class ShowFileDriver {

	public static void main(String[] args) {
	
		try(ShowFile sFile = new ShowFile()){
			System.out.println(sFile.returnContentsOfFile());
		} catch (Exception e) {
			// Handle the exception
		}

	}

}

Running this program will demonstrate that the close method was called when the try statement ended.

I think therefore I am
Be yourself; everyone else is already taken
So many books, so little time

Cleaning up resources...

2.6 Explicitly Calling the Garbage Collector

As previously explained, the garbage collector runs as a low priority background thread. However, you can request the JVM to run the collector using the System or Runtime classes:

  • System.gc()
  • Runtime.getRuntime().gc() 

It is not regarded as good practice to call the GC directly because:

  • It does not guarantee the GC will run right away or that it will even run at all.
  • Running the GC takes up resources. This may adversely affect the performance of your application. For example, it may suspend all user threads while the process runs.

You may consider calling the GC explicitly if you are debugging memory issues in an application.

3. Summary

In this article, we examined garbage collection in Java. We looked at the Garbage Collector and discussed what circumstances make an object eligible for collection. We also explored the topics of object reachability and object cleanup. Finally, we demonstrated how to call the garbage collector in our code.

4. Additional knowledge

5. Download the Source Code

Download
You can download the full source code of this example here: Garbage Collection in Java

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

 

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

 

and many more ....

 

Receive Java & Developer job alerts in your Area

 

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments