Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recover from java.lang.OutOfMemoryError

So today while learning Java, I finally encountered this particular error. It seems that this error is pretty prevalent and trying to recover from it has garnered mixed reactions. Some think it is useful in certain scenarios so its a good 'good to know', some have used it in their projects, while others vehemently oppose the idea of catching this error and then a lot of others are just as confused as me.

Edit: Oh btw, this is the error that I have encountered. I wish to catch these errors and decrease the value of incrementor by 1/10th next time until another error is found
(and so on... until I find the upper bound) This is the error I've encountered

Since I'm taking my baby steps in Java and cannot find anything much specific on this topic, I'd like to ask your help on this particular example:

public class SpeedDemoClass {
        static int iterations=0;
        static int incrementor=10000000;
    public static void main(String[] args) {
        while(incrementor>1){
            try{
              iterations=iterations+incrementor;
              iterator(iterations);
            }
            catch(Exception e){
                System.out.println("So this is the limiting error: "+e);
                iterations=iterations-incrementor;
                incrementor=incrementor/10;
                iterations=iterations+incrementor;
            }
        }
        System.out.println("The upper limit of iterations is: "+iterations);
    }

    public static void iterator(int a){
            long start_time= System.currentTimeMillis();
            StringBuilder sbuild= new StringBuilder("JAVA");
            for(int i=0;i<a;i++){
                sbuild.append("JAVA");
            }
            System.out.println("Performing "+a+" append operations;"
                    +"process completed in :"
                    +(System.currentTimeMillis()-start_time)+"ms");
    }
}

Did you try compiling it?

Ofcourse, it does not work

Here's a short description on what I'm trying to do!

I am trying to do the following:

  1. Initialize incrementor=10000000 and iterations=0 and pass the result of incrementor=incrementor+iterations to iterator().
  2. If there is an Error, the program should catch it and then decrease iterations* by **incrementor, then divide incrementor by 10, then try this again
  3. Repeat steps 1 to 2 until, it starts working.
  4. Goal is to find values of iterations where it produces error and stay below that level after each iteration until the upper limit of the value of iterations is found
    (i.e. when incrementor becomes 0)

With my own manual tests, I have found out the value of this to be 92,274,686. That's the magic number. I don't know why it is so, and whether or not it is that value for my own computer only. It would be awesome if someone could post a modified code that could spit out this result.

like image 867
Siddhant Rimal Avatar asked Aug 29 '16 14:08

Siddhant Rimal


People also ask

Can the JVM recover from an OutOfMemoryError without a restart?

In other words if an OOME is thrown in an application server (jboss/websphere/..) do I have to restart it? No you don't have to restart. But it is probably wise to, especially if you don't have a good / automated way of checking that the service is running correctly. The JVM will recover just fine.

What causes Java Lang OutOfMemoryError?

lang. OutOfMemoryError exception. Usually, this error is thrown when there is insufficient space to allocate an object in the Java heap. In this case, The garbage collector cannot make space available to accommodate a new object, and the heap cannot be expanded further.

How do I fix memory heap?

There are several ways to eliminate a heap memory issue: Increase the maximum amount of heap available to the VM using the -Xmx VM argument. Use partitioning to distribute the data over additional machines. Overflow or expire the region data to reduce the heap memory footprint of the regions.


2 Answers

You catch Exception, but OutOfMemoryError is an Error. Note that Error and Exception are two different classes in Java! Both implement Throwable, though.

The catch clause restricts the type of Throwable classes to be caught. As Error is not an Exception, your code won't catch OutOfMemoryError.

like image 91
Martin Nyolt Avatar answered Sep 30 '22 19:09

Martin Nyolt


That "magic number" will change if you allocate some extra objects that use up memory, use a PC with less memory etc. or allocate memory smart. Trying to estimate memory consumption brute-force is a bad idea!

Instead, understand how Java memory allocations work, how the memory layout of a string builder is, and how to control this. Here, you should study the method ensureCapacityInternal.

Look at the error you get - in particular the classes and line numbers.

I bet that if you replace this line:

StringBuilder sbuild= new StringBuilder("JAVA");

by

StringBuilder sbuild= new StringBuilder(500000000);

Then you get much further before seeing an OOM error. Catching this error is not a very clever way. There are some nice variants to observe memory consumption; but you really should use them only once you have understood memory organization of Java, so you don't draw wrong conclusions.

Your PC probably has 8 GB of RAM? Try using java -Xmx7500m. You may be able to go 3x as far. Because by default, Java only uses 25% of your memory simply to allow other processes to use some memory, too. If you want Java to use all your memory, you have to tell it that this is desired.

like image 45
Has QUIT--Anony-Mousse Avatar answered Sep 30 '22 18:09

Has QUIT--Anony-Mousse