Ways I handled my OutOfMemoryErrors
bankstatementconverter.com
bankstatementconverter.com
It probably makes sense for unmanaged code to die just on OOM: it (presumably) has "accurate" memory tracking so if it runs out of memory, then it actually can't progress forward. But for managed environments OOM just means that it's time to do a stop-the-world, process-wide GC in every allocated heap.
I've seen several cases in Erlang where a long-living process would do some heavy processing with binaries (they live in a separate binary heap devoted specifically to storing binaries), send the results and then go to sleep. It leads to the situation where there would be a large amount of unneeded binaries polluting the heap that can't be collected because they are still referenced by some process; if that process did a GC, those references would go away but it didn't because those references are quite small and don't make the process's heap large enough to trigger GC. And since in Erlang GC is done only per process, not globally, there is not much one can do besides judicious sprinkling of "erlang:garbage_collect()" and "hibernate" through the codebase.
The probability of hitting the limit is proportional to the allocation size, so the program is most likely to hit it early on something big and easy to back out of (a buffer for a whole file, or an image bitmap) rather than literally have 0 bytes left.
Additionally, allocators typically have per-size memory pools and free lists, so even when one small allocation fails, there's still a chance that other size classes will be available.
In something like C error manual handling and freeing is hard, so the error code paths in unexpected places are likely to be untested and buggy. But with something like Rust the compiler writes cleanup code for you, so it can clean up precisely every time (if only Rust's libstd wasn't committing a suicide on OOM :()
-XX:+ExitOnOutOfMemoryError
-XX:+CrashOnOutOfMemoryError
E.g. text.regionMatches(true, index, substring, 0, substring.length())
$ java -XX:+PrintCommandLineFlags -version
-XX:G1ConcRefinementThreads=8 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=268435456 -XX:MaxHeapSize=4294967296 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC
openjdk version "11.0.7" 2020-04-14 OpenJDK Runtime Environment (build 11.0.7+10) OpenJDK 64-Bit Server VM (build 11.0.7+10, mixed mode)