0

We have to deal with a class library that does a

catch(Throwable e) {log.error("some message", e)}

but otherwise ignores the problem. Other than running an external command as described in https://stackoverflow.com/a/3878199/2954288, is there some internal global state in the JVM that can be queried to see if an OutOfMemoryError has happened since the startup?

My question is not a duplicate of: Is it a bad practice to catch Throwable?. I am not asking whether or not we should catch(Throwable). I am asking whether a certain way to deal with it exists.

Community
  • 1
  • 1
Harald
  • 4,575
  • 5
  • 33
  • 72
  • My rule of thumb is "never trust a JVM that has thrown an OOME" because it might look like it is working OK while in fact it isn't. And restarting it will require an external command. – piet.t Aug 25 '16 at 07:28
  • 2
    @piet.t how about another: "never trust a library which swallows `Throwable`". Who knows what other madness is in there... – Andy Turner Aug 25 '16 at 07:38
  • Exactly. Nevertheless I am in a situation where I would like to at least try to set a last mark before exiting. – Harald Aug 25 '16 at 07:38
  • See http://stackoverflow.com/questions/2679330/catching-java-lang-outofmemoryerror – Raedwald Aug 25 '16 at 08:37
  • Possible duplicate of [Is it a bad practice to catch Throwable?](http://stackoverflow.com/questions/6083248/is-it-a-bad-practice-to-catch-throwable) – Raedwald Aug 25 '16 at 08:39
  • You should regard that as a bug in the class library and ask for it to be fixed. – Raedwald Aug 25 '16 at 08:40
  • @Raedwald: certainly not a duplicate of the question you mention, since there is no question that the library should not catch(Throwable). And yes, a bug report is under way. – Harald Aug 25 '16 at 09:55

2 Answers2

1

Is there some internal global state in the JVM that can be queried to see if an OutOfMemoryError has happened since the startup

Yes, there is a variable out_of_memory_reported. It is internal and is not supposed to be read from outside. Though you can do this with gdb, for example:

$ gdb -p PID

(gdb) p 'report_java_out_of_memory(char const*)::out_of_memory_reported'
$1 = 0

If you'd like a reliable way to intercept all OutOfMemoryErrors from within Java application, whether they are caught or not, you can use JVMTI Exception Callback. The example can be found here.

Community
  • 1
  • 1
apangin
  • 92,924
  • 10
  • 193
  • 247
0

Catching OutOfMemoryError in the path of all possible places where it occurs ... it's not really possible as it can occurs in any Java codes, and internally in the JVM.

When the JVM emits an OOME, sometimes it's recoverable but usually not, so catching it inside your will generally lead to nothing as the JVM will be unusable (it is in a state where it cannot allocate more memory so you cannot process any step in your program)

If you need to know whether or not your application generate OOME and a way to take action, you need to do this from an external point, the easiest way to do this is to use the standard way that the JVM offers you using some jvm starting option.

Usually, for dealing with OOME you use the following JVM starting options:

  • -XX:+HeapDumpOnOutOfMemoryError tells the JVM to generate a heap dump on OOME so you can analyse it further (for example with Eclipse MAT: http://www.eclipse.org/mat/)
  • -XX:OnOutOfMemoryError="<cmd args>;<cmd args>" tells the JVM to launch a command on the host in case of OOME. By this you can for example send an email and restart your server!

More informations on statup options ca be found here : http://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

Vladimir Vagaytsev
  • 2,871
  • 9
  • 33
  • 36
loicmathieu
  • 5,181
  • 26
  • 31
  • Do those flags cause the JVM to do things for *all* OOMEs, or just the uncaught ones? – Andy Turner Aug 25 '16 at 07:39
  • I am not after catching it, since I can't anyway. I just wonder if there is some flag within the JVM that would tell me after the fact that bad things have happened. – Harald Aug 25 '16 at 07:49
  • That's why I give you the two usefull flags ;) I don't think there is anything else that is usable because as the JVM didn't have anymore memory, it cannot records diagnostic data regarding the cause of OOME ... The only way is to generate a dump and analyse it after as I suggest in my answer. – loicmathieu Aug 25 '16 at 08:01