3

I'm designing a solution, which includes a C++ library and several Java applications using the library via JNI.

C++ library allocates native memory massively. It's possible to detect from C++ code when this allocation fails. Failure to allocate should be reported to Java code with throwing something throwable.

The 2 options are considered:

  1. Throw java.lang.OutOfMemoryError from my C++ code
  2. Add mylibrary.MyLibraryOutOfMemoryError (extends java.lang.RuntimeException or java.lang.Error), and throw it

What would be the right option and why?

user207421
  • 305,947
  • 44
  • 307
  • 483
  • You must **never** throw an OOM error, let the application throw it. Also, you **must not** handle errors, they're meant to terminate the application. – Luiggi Mendoza Jul 11 '13 at 17:41
  • Thanks for your response! Could you please clarify (a) why OOM should not be thrown from my JNI code? e.g. here they even provided a handy method to throw specifically OOM: http://stackoverflow.com/questions/230689/best-way-to-throw-exceptions-in-jni-code (b) what specifically do you mean with letting application throw it? – user2573701 Jul 11 '13 at 17:56
  • From what you seem to say, such an error is not recoverable; you should probably go with a `RuntimeException`, then. An allocation failure from native code does not prevent the JVM to work, but prevents your application from operating normally. If the JVM itself fails to allocate, you'll see an `Error` soon enough anyway. – fge Jul 11 '13 at 17:59
  • @Luigi I can't agree with your second assertion. RMI for example catches OutOfMemoryError. 'Never' is too strong here. – user207421 Jul 11 '13 at 23:26

1 Answers1

5

OutOfMemoryError has a specific meaning:

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

Since it is a native heap allocation that's failing, it would be inappropriate for your code to throw this error. Notwithstanding what ByteBuffer.allocateDirect() does.

I would recommend that you create your own exception, extending Error. It should not be a checked exception, as there is little/nothing that a running program could do to avoid the error.

parsifal
  • 811
  • 7
  • 4
  • It should extend `Error` and not `RuntimeException`. Otherwise it would be caught by catch handlers for `Exception` which is usually not what you want when you're out of memory. (`OutOfMemoryError` is also an `Error` and not a `RuntimeException`) – main-- Jul 11 '13 at 19:01
  • @main-- - That's a valid point; I've edited my response. Be aware, however, that many "last-ditch" catch blocks (including `Thread`'s uncaught exception handler) actually catch `Throwable` and not `Exception`. – parsifal Jul 11 '13 at 19:09
  • Thanks! "...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..." <= it looks like the key is what is meant by JVM from Java code perspective here: for me it could be (a) JVM, (b) JVM + all loaded native libraries (including mine). – user2573701 Jul 11 '13 at 21:23
  • 1
    Here is more info on OOM: http://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-VM/html/memleaks.html It says that OOM can have several reasons. It has this bit: "3.1 ...A java.lang.OutOfMemoryError can also be thrown by native library code when a native allocation cannot be satisfied, for example, if swap space is low..." Is it about native libs written by application developers? Is 3.1.5 specifically for my case? Or is it about native libs that are part of JVM only? – user2573701 Jul 11 '13 at 21:27
  • Also, yes, failure to allocate memory is non-recoverable. The best option a Java application using the lib has is to shutdown gracefully (to be restarted properly). – user2573701 Jul 11 '13 at 21:32
  • It is clear that throwing/catching/extending Errors in application **Java** code is not welcome. But it is not clear about application **C++** code used via JNI. Is it OK for this code to throw Errors? Is it OK to re-use Errors (eg OOMError) that come with JVM? Techincally it's possible, but is it intended by design? Strangely can't find guidelines and/or reasoning in JNI docs. – user2573701 Jul 11 '13 at 21:41
  • @user2573701 - I certainly can't point you to a hard rule. As my comment about bytebuffers and your technote reference indicate, there are cases where OOM will be thrown due to native allocations. I'm uncomfortable with that, even when Sun does it, as it seems to sidestep the guarantee (in the JLS) that the VM will have tried to free up sufficient memory before OOM. I also happen to like application-specific exceptions. – parsifal Jul 12 '13 at 13:40
  • Thanks for all your input so far. – user2573701 Jul 14 '13 at 15:13
  • Still it would be great to find any guidelines from JNI/Java designers about how JNI code is expected to report non-recoverable errors. – user2573701 Jul 14 '13 at 15:21
  • E.g. here is an explanation on why there are no subclasses of OOM: http://stackoverflow.com/questions/6244055/why-there-are-no-outofmemoryerror-subclasses . It makes me think about why we should create a new custom error for our case of OOM. If there are no subclasses of OOM in Java, why would we need a new subclass of Error for our case of lack of memory. – user2573701 Jul 14 '13 at 15:21