Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login
×

You must be logged to download. Click here to login

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

Controlling Memory Leaks in Java

In this article, we will see a complete overview about memory leaks in Java world and the main ways you can use to prevent them.

Contrary to what many people think, an application written in Java can indeed present memory leak problems. Unfortunately, a large number of Java programmers think memory leak is something for C/C++ and the Java Garbage Collector solves this problem completely. In this article, I intend to show that although the Garbage Collector works very well, it cannot do magic.

Memory leak means exactly what its name says: memory leak. It can be of two types:

  1. Memory Blocks: are allocated and available for use by the application, but are not accessible because the application has no pointer* pointing to this memory area. Therefore, these memory blocks may neither be used for the application and nor for other processes.
  2. Memory Blocks: have data that could be released because they are inaccessible and that (because they were forgotten) are still referenced in the code even without being used, and cannot be released.

The situation 1 is very common in C/C++. Allocates an amount of memory using malloc* function, for example, and in the sequence the programmer causes the pointer to this area pass memory to point to another location, losing the initial reference. In Java this type of memory leak does not occur because the Garbage Collector is able to detect allocated and unreferenced memory blocks and release them for later use.

It is the situation 2 where lies the problem. However, before explaining how this problem may occur and how to prevent it, we must understand a little more about how the Java Garbage Collector works.

*1 A pointer is a variable that points to a memory address. It is a very common term in C/C++ and you are wrong to think that Java does not have pointers. When an object is created using new, the variable that receives the object is actually a pointer that points to a memory address that contains the object.

*2 The malloc() function is part of the C API. Its function is to allocate the desired amount of memory (provided as a parameter). The return of this function is a pointer to the newly created area of memory.

The Role of the Garbage Collector

One of the great advantages of the Java programming language on the lower level is the presence of the Garbage Collector. The function of it is to scour the memory behind allocated blocks that no longer have to be referenced by the application. When the Garbage Collector faces such that situation, it deallocates memory, making it available to be used again by the application.

See why the way Garbage Collector works in Java is very easy. Note the code in Listing 1.

Listing 1. Example of main method.

public static void main(String[] args) throws Exception {
	int[] array = null;  

	while(true) {  
		array = new int[1000];  
		System.out.println("Free Bytes : " + Runtime.getRuntime().freeMemory());  
		Thread.sleep(200);  
	}
}

This code is running in an endless loop. Each iteration of the loop, an array of 1000 integer’s positions is created. Each time the loop is executed, the amount of free bytes is shown. At first you may think: will this application end up with the memory of the JVM? Actually, that is not what happens. When you run the program at any given time, you will see the following output shown in Listing 2.

Listing 2. Program output.

Free Bytes: 1530520
Free Bytes: 1530520
Free Bytes: 1530520
Free Bytes: 1526504
Free Bytes: 1522488
Free Bytes: 1518472
Free Bytes: 1514456
Free Bytes: 1510440
Free Bytes: 1912792
Free Bytes: 1912792
Free Bytes: 1908776
Free Bytes: 1904760
Free Bytes: 1900744
Free Bytes: 1896728
Free Bytes: 1892712

The memory was running and it suddenly increased. The explanation for this is simple. When the loop is executed, the array is created. In the next iteration of the loop, the array created in the previous iteration is not referenced by anyone else (note that the array variable stop pointing to the old array and went on to point to the new array, making the old array inaccessible). At one point, the JVM sees the fall of the available memory and puts the Garbage Collector to run. The Garbage Collector then discovers that this memory was being allocated over the loops is inaccessible and releases it. It is, at this point, that we can see the available memory increases.

After seeing this code running, you must be wondering: how do I know when the Garbage Collector will run? You cannot know. The control of the Garbage Collector execution is from the JVM. When the JVM decides it's time to run it, it will run. Note that running the Garbage Collector all the time would not be recommended, since it takes up computer resources.

Another important point about the Garbage Collector is that as it is controlled by the JVM, it is not possible to force its execution programmatically. The most that can be done is to call System.gc() method (or Runtime.getRuntime().gc()). This method notifies the JVM that the application would like the Garbage Collector to be executed, but does not guarantee that it will actually be executed at the desired time.

The finalize method

The Java Object class has a method called finalize(), which can be overridden by classes that inherit from Object (that is, any class). When the Garbage Collector decides that a particular object will be destroyed for not being more referenced, it calls the finalize() method on the object just before destroying it.

Despite the finalize() method is a chance the programmer has to release resources associated with the object at the time that it will be destroyed, overriding the finalize() is not recommended at all. The reason is simple: as there is no guarantee that the object is destroyed, there is also no guarantee that finalize() will run. The Oracle itself does not recommend the override of the finalize() method. The release of resources can be made in other ways, such as using blocks try/catch/finally and/or by the establishment of specific methods for this purpose (close() method, for example).

Causing a memory leak in Java

After understanding what is a memory leak and how the Java Garbage Collector works, we will now see how to cause a memory leak in Java and what to do to avoid it. First, I would like to stress that memory leaks are hard to find (it is sometimes necessary to resort to external tools) and are always caused by a programming error. Usually programmers do not care much about them until the moment they start to consume an excessive amount of memory or even topple the JVM (when the memory finishes, the JVM throws a java.lang.OutOfMemoryError and ends).

As we saw, the Garbage Collector is able to detect non-referenced objects and destroy them, freeing the memory. To create a memory leak just keep the reference to one or more objects in the code, even without using it later. Thus, the Garbage Collector can never destroy objects, and they will continue to exist in memory even not being more accessible. Watch this simple example implementation of a stack in Listing 3.

Listing 3. Example of a stack.

public class Stack {
	private List stack = new ArrayList();  
	int count = 0;  
 
	public void push(Object obj) {  
		pilha.add(count++, obj);  
	}
  
	public Object pop() {  
		if(count == 0) {  
			return null;  
		}
		return pilha.get(--count);  
	}
}

Each time an element is placed or removed from the stack, a counter controls the position of the last element. This is a visible case of memory leak. The stack has registered references to all the objects in it. However, much as the objects are all removed from the stack, the stack will continue referencing the removed objects, which make it impossible to Gargabe Collector to recover this memory.

To resolve the situation in this case, simply delete the reference to the object when it is removed from the stack (Listing 4).

Listing 4. Resolving the problem.

public class Stack {
	private List stack = new ArrayList();  
	int count = 0;  

	public void push(Object obj) {  
		pilha.add(count++, obj);  
	}  

	public Object pop() {  
		if(count == 0) {  
			return null;  
		} 

		Object obj = stack.get(--count);  
		stack.set(count, null);  
		return obj;  
	}
}

Assign the object reference to null will cause the battery no longer references the object, allowing for the Garbage Collector the destruction of it.

This example is intended to show how memory leak in Java is possible. It is difficult for anyone to implement a stack in this manner (even more Java already has a stack class for this purpose). Anyway, imagine a similar situation where thousands or even millions of objects are inaccessible and yet referenced. In an application running without stopping in an application server, for example, this can lead to the termination of the JVM out of memory after a few days of accumulated memory leaks. In such that situation, finding the error can be an extremely complicated and laborious task.

Recommendations to avoid memory leaks

Believe me: following some recommendations to avoid memory leaks is much easier than detecting them after the code has been finished. As the Garbage Collector greatly facilitates the work of the programmer, just pay attention to some key points that are common causes of memory leaks:

  • Beware of objects collections (arrays, lists, maps, vectors, etc.). Sometimes, they can hold references to objects that are no longer needed;
  • Also, related to objects collections, if they are static or last throughout the application life time, care should be taken;
  • When programming situations where you need to register event listeners to objects, take care to remove the records of these objects if they are no longer needed. Bottom line: delete all references to unnecessary objects. By doing this, the Garbage Collector will be able to do its job thoroughly and you will be free of memory leaks in your applications.

This article sought to show that there are memory leaks in Java, contrary to what many people think. It has been shown how to create a memory leak situation and how to take care that such situations are avoided in order to not impair the applications.



Web developer and passioned for web design, SEO and front end technologies.

What did you think of this post?
Services
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login