Recently, I wrote a Java application which, when run, requires quite a bit of memory and I started to get the OutOfMemory error:
Error: java.lang.OutOfMemoryError: Java heap space
This often happens when we need to run memory-guzzling programs. Following are a few ways to solve such problems.
First of all, lets understand what is heap space. Well, Java uses memory mainly in the arrangements of heap and stack. Java keeps the parameters that are passed from a calling method to a called method, in the form of a stack structure (i.e. parameters are pushed in and popped out of the stack as per the need). On the other hand, heap is a randomly accessed memory space where Java creates and keeps objects. Java creates the object within this heap space wherever it finds room enough to contain the object. So, when you create a new object (e.g. new String(); ) the object gets created in the heap space and occupies the memory which it can fit into. During the garbage collection, Java frees the heap space of those objects which are no longer referenced. But if the number of referenced (i.e. “required”) objects keeps on increasing and we don't deference them -the JVM runs out of the heap space.
The amount of memory that a class would require depends upon the number and type of its data members.
- The class itself requires minimum of 8 bytes
- Every data member requires 4 bytes (long and double require 8 bytes). Even a Boolean variable is use 4 bytes though it only needs one bit to get stored.
- Amount of used memory grows in chunks of 8 bytes
The first step to get around this problem should be to go through the program and see how it could be modified so as to make it use lesser memory. Since long the cost of memory has been extremely low in comparison with what it was during 1960s. And programmers have become pretty extravagant in terms of memory allowance to their programs. However still, more often than not, we need to write programs that require more memory than available. Frugality in context of memory usage is always good because not only it reduces the chances of program crash but also sometimes it enhances the speed of execution.
You should set objects to be null when they are no longer required in your code. This is even more important if you are running a loop in which you create object(s) but then don't discard them when they are not required.
The second step towards the memory usage optimization could be to explicitly call the Garbage Collection method. Java automatically calls this method as and when required and frees up the memory space that contains the objects which are no longer referenced. But you can also call this method explicitly in your code (for example, after a “big task” is accomplished and next “big task” is about to begin). To call the garbage collector, use:
You can monitor the status of memory before and after gc() method is called.
System.out.println("nnCalling Garbage Collectornn"); System.out.println("Free memory BEFORE: " + Runtime.getRuntime().freeMemory()); Runtime.getRuntime().gc(); System.out.println("Free memory AFTER : " + Runtime.getRuntime().freeMemory()); System.out.println("nnGarbage collection finishednn");
freememory() method returns amount of free memory available measured in bytes. For other methods provided by Runtime class see Java API
Efforts for memory usage optimization notwithstanding, sometimes JVM does indeed needs more memory. In such cases we can tell JVM via command line to use a specified amount of memory:
java -Xms2000m -Xmx3500m
-Xms and -Xmx switches specify the amount of swap space (virtual memory) that JVM can use in your machine.
-Xms specifies the minimum (i.e. initial) amount of memory
-Xmx specifies the maximum amount of memory that JVM could use.
These memory values should be specified in Megabytes.
So, this was about Java manages memory through heap space and garbage collection mechanism. These are smart choices and every Java programmer should have clear understanding of how Java handles memory. Only you'll be able to efficiently work on memory intensive programs.