7

Possible Duplicate:
Catching java.lang.OutOfMemoryError

OutOfMemoryError are:

Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector

Java says:

An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions.

This feels like hearing:

If you are drowning, be reasonable: you should not try to swim upwards to keep your head above water. Death is typically resulting from abnormal conditions.

Let's imagine a scenario where one is running a service. For some reason, another application on the same server is eating a lot of memory, causing an unexpected OOM in your service. Is it such a bad idea to try to reduce this service's memory consumption in order to remain available to user?

Or is there something more fundamental happening at the JVM level preventing the implementation of such a solution after the OOM has been thrown?

Community
  • 1
  • 1
Jérôme Verstrynge
  • 57,710
  • 92
  • 283
  • 453
  • @aix I could cut loose a couple of references to some data structures by setting them to null even if I did not save them properly while still be ok with that in dramatic situations. – Jérôme Verstrynge Sep 08 '11 at 16:18
  • @dogbane Your reference does not answer my question, this question is not a duplicate. – Jérôme Verstrynge Sep 08 '11 at 16:21
  • A better analogy would be: Your driving a car that catches on fire. Do not attempt to continue and reach your destination. Pull onto the hard shoulder. – Jim Sep 08 '11 at 16:23
  • If your service could opt to use less memory after an OOM then why not ALWAYS use less memory in order to never get the OOM? – Corey Ogburn Sep 08 '11 at 16:26
  • @Jim If it is a plane flying over the Atlantic, trying to fix it while flying to avoid the crash seems legitimate to me. – Jérôme Verstrynge Sep 08 '11 at 16:27
  • 3
    @JVerstry In this case, the plane is nose-diving into the Atlantic and you are just 100 metres away from the water surface, with both the engines failed. There's nothing you can do about it. Let it sink in! – adarshr Sep 08 '11 at 16:30
  • @Corey I am talking about exceptional circumstances (I agree memory allocation should be properly planed and allocated to the JVM under normal circumstances) – Jérôme Verstrynge Sep 08 '11 at 16:32
  • Rather than wait for an OOME and then take some action, it is better to setup a scenario where it won't happen in the first place. e.g. If you have a couple of objects you could discard, you can use a SoftReference for each and it will do this automatically if the memory is needed. – Peter Lawrey Sep 08 '11 at 16:51
  • Adding on to @peter's comment, java also provides jmx support using which after reaching a certain memory threshold, say 75%, you can take clean up actions or suspend your application till enough memory is recovered instead of crashing via OOME. – Scorpion Sep 08 '11 at 17:20
  • I know about SoftReference and JMX's functionality. I was really going for the critical case... – Jérôme Verstrynge Sep 08 '11 at 17:21
  • @Jverstry, I have done it before to ensure a graceful shut down of all thread. If you don't catch it, you can have one thread die, leaving the other threads still running and the application in an odd state. So you could argue its good idea to always catch this error. ;) – Peter Lawrey Sep 08 '11 at 17:50
  • @Peter Good to know. In fact, I am considering implementing this with AspectJ to catch critical/desperate cases. You can't always avoid being forced to put a knee down, but it does not mean you should not try to fight back. – Jérôme Verstrynge Sep 08 '11 at 17:56
  • With memory being relatively cheap these days (my PC has 24 GB), you should be able to set the maximum memory so high that if your application ever uses that much you want it to die. ;) – Peter Lawrey Sep 08 '11 at 18:00

5 Answers5

3

As you quoted

Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector

At that point your are screwed. That description implies that Java/the JVM can't get enough resources to operate, and if that is true, executing more Java code to fix the problem would itself be problematic.

A good analogy is that your car has run out of gas, and you want to fix that by stepping on the accelerator.

A better solution is to do capacity planning and make sure

1) Your servers have enough memory to do their jobs
2) The services running on your servers perform within spec and don't consume more than a certain amount of resources.

hvgotcodes
  • 118,147
  • 33
  • 203
  • 236
0

The problem here is that by OOM is an error which should not occur under normal circumstances. By catching it and trying to release memory, you are likely obscuring some sort of leak or unintended behaviour elsewhere.

If you do get OOM, perhaps it's because you did not configure the JVM to use more memory.

Mike Kwan
  • 24,123
  • 12
  • 63
  • 96
  • Agreed, but I could log that issue after releasing memory and calling the gc myself. It is not impossible. – Jérôme Verstrynge Sep 08 '11 at 16:26
  • 1
    If you can fix it, and you know why the error occurred and it was legitimate then by all means do so. But most of the time, when you get an OOM you won't know and it will be very difficult to recover because you'll find you're very limited as to what you can do once your VM is out of memory. – Mike Kwan Sep 08 '11 at 16:32
-1

It is a bad idea. Primarily because OutOfMemoryError is an Error not an Exception - An Error "indicates serious issues that a reasonable application should not try to catch."

Instead, analyse your possible scenarios and apply fixes based on information provided in this PDF

ring bearer
  • 20,383
  • 7
  • 59
  • 72
  • 1
    Ok, but what if you can fix the plane flying to avoid the crash? Is there any reason no to do so? That is my question... – Jérôme Verstrynge Sep 08 '11 at 16:25
  • Man,what an analogy! So a plane crash occurs due to some condition that most of the time is out of human control. For that, there are emergency procedures defined so that still some souls can be saved. Similarly an application should have early warning in place if it is that critical and should have a recovery process - if reasonable. If you are out to catch `OutOfMemoryError` where all would you catch that? and most of the time when you catch it, there is nothing much that you can do about it. Just like a plane crashing in mid Atlantic ;even if you had parachutes the chances of surviving is 0 – ring bearer Sep 08 '11 at 16:32
-1

It is useless. Because at the moment the error is catched, you may be so short of heap memory that any new object creation could throw a new OOME. Having such an small margin of maneuver in the catch means that the only action you could take is to exit.

Test this snippet, and tell me what your output is:

      import java.util.LinkedList;
      import java.util.List;

      public class OOMErrorTest {


        public static void main(String[] args) {
            List<Long> ll = new LinkedList<Long>();

            try {
                long l = 0;
                while(true){
                    ll.add(new Long(l++));
                }
            } catch(OutOfMemoryError oome){         
                System.out.println("Error catched!!");
                System.out.println("size:" +ll.size());
            }
            System.out.println("Test finished");
        }

      }

But strictly speaking, yes, these are catchable.

Mister Smith
  • 27,417
  • 21
  • 110
  • 193
-1

You can't really recover from OOM.

There's one reason however to try and catch anything - that's what the "catch-throwable" faction told me when we did exactly that in a project I no longer work in - that one reason being: try to log what happened. Because if you don't know what happened it is hard to figure out how to get the software back up and running.

There's also a big "but" to that one reason: it won't work usually.

Errors usually can't be fixed from within your running code, that's why there is that difference.

Yashima
  • 2,248
  • 2
  • 23
  • 39