Site icon Geeknizer

Prevent and Recover from Java OutOfMemory Error

Like any other programming language, Java puts a restriction on amount of memory you can use for the execution of programs. The difference being – Most other languages like C++, PHP, user has the power and the pain of allocating and handling the memory operation.

Since Java uses JVM, the developer’s pain of thinking about memory allocation is gone but sudden deaths like OutOfMemoryException become inevitable for Memory intensive programming. This is exactly what we are going to discuss here – How to prevent it and recover from it.

Need of Recovery

The advantage can be seen almost everywhere. Let’s take example for distributed J2EE applications, which involves huge databases and processing of a large amount of data within a class, sudden death of Java execution threads can cause trouble by creating stale transactions, database connections and what not. If we can, somehow, prevent this situation, it will ensure there will be no data corruption and the JVM, which may host multiple applications or atleast multiple threads, is able to recover from the memory errors. You can always call the GC & runFinalization once this error occurs to free some memory.

Methodology

The easiest prevention, as you already know is to increasing the JVM arguments to increase maximum memory. But it’s not what we intend to discuss, rather a better approach.

Runtime.getRuntime().freeMemory()

freeMemory() gives the amount of free memory at runtime. This gives you free memory at any instant,  but it changes as the memory requirements change for the program when JVM actively allocates more space for execution till the upperlimit -Xmx is reached.

We need an effective way to tackle this. We will be using one of the utility classes from Apache Derby V10.6 Internals called LowMemory. The class has the below 2 methods drawing our intrest.

void setLowMemory() – Sets a low memory watermark where the owner of this object just hit an OutOfMemoryError.

boolean isLowMemory() – Returns true if a low memory water mark has been set and the current free memory is lower than it.

public class MemoryTest {
    public static void main(String[] args) throws Exception {
		MemoryTest memoryTest = new MemoryTest();
		LowMemory lowMem = new LowMemory();
		long[] memLongVar = new long[80000];
		lowMem.setLowMemory();
		memoryTest.fillMemory(lowMem);
    }
    public void fillMemory(LowMemory lowMem) throws Exception {
		int voidSpace = 20;
		for (int outIterator=1;outIterator<1024;outIterator++) {
			System.out.println ("Iteration " + outIterator
				+ "Free: " + Runtime.getRuntime().freeMemory());
			int inIterator=10;
			if (!lowMemory.isLowMemory()) {
				int[] memIntVar = new int[voidSpace];
				do {
					memIntVar[inIterator]=0;
					inIterator--;
				}
				while(inIterator>0);
				voidSpace = voidSpace * 10;

			} else {
				System.out.println ("Memory lower than threshold,
				will exit.");
				doSomeRecoveryMechanism();
				// Quit with Notification,prevent other Threads from dying
		                break;

} } } }

Updated: By following an application dependent logic to gracefully exit, now your other enterprise applications will not all die in one fusion reaction, and we can prevent the single point of failure from occuring to a great extent. Chance are there that other threads finish the execution ion next couple of seconds and it frees-up some memory for your applications.

If other application continue to eat more memory, there is no way you can recover from this.
I’m open to your comments, do let me know what you think.

Exit mobile version