java.is.for.desktop
java.is.for.desktop

Reputation: 11216

Tune Java GC, so that it would immediately throw OOME, rather than slow down indeterminately

I've noticed, that sometimes, when memory is nearly exhausted, the GC is trying to complete at any price of performance (causes nearly freeze of the program, sometimes multiple minutes), rather that just throw an OOME (OutOfMemoryError) immediately.

Is there a way to tune the GC concerning this aspect?

Slowing down the program to nearly zero-speed makes it unresponsive. In certain cases it would be better to have a response "I'm dead" rather than no response at all.

Upvotes: 5

Views: 1166

Answers (4)

java.is.for.desktop
java.is.for.desktop

Reputation: 11216

Well, turns out, there is a solution since Java8 b92:

-XX:+ExitOnOutOfMemoryError
When you enable this option, the JVM exits on the first occurrence of an out-of-memory error. It can be used if you prefer restarting an instance of the JVM rather than handling out of memory errors.

-XX:+CrashOnOutOfMemoryError
If this option is enabled, when an out-of-memory error occurs, the JVM crashes and produces text and binary crash files (if core files are enabled).

A good idea is to combine one of the above options with the good old -XX:+HeapDumpOnOutOfMemoryError

I tested these options, they actually work as expected!

Links

See the feature description

See List of changes in that Java release

Upvotes: 0

mogronalol
mogronalol

Reputation: 3015

I strongly advice against this, Java trying to GC rather than immediately throwing an OutOfMemoryException makes far much more sense - don't make your application fall over unless every alternative has been exhausted.

If your application is running out of memory, you should be increasing your max heap size or looking at it's performance in terms of memory allocation and seeing if it can be optimised.

Some things to look at would be:

  • Use weak references in places where your objects would not be required if not referenced anywhere else.
  • Don't allocated larger objects than you need (ie storing a huge array of 100 objects when you are only going to need access to three of them through the array lifecycle), or using a long datatype when you only need to store eight values.
  • Don't hold onto references to objects longer than you would need!

Edit: I think you misunderstand my point. If you accidentally leave a live reference to an object that no longer needs to be used it will obviously still not be garbage collected. This is nothing to do with nulling just incase - a typical example to this would be using a large object for a specific purpose, but when it goes out of scope it is not GC because a live reference has accidentally been left elsewhere, somewhere that you don't know about causing a leak. A typical example of this would be in a hashtable lookup which can be solved with weak references as it will be eligible for GC when only weakly reachable.

Regardless these are just general ideas off the top of my head on how to improve performance with memory allocation. The point I am trying to make is that asking how to throw an OutOfMemory error quicker rather than letting Java GC try it's best to free up space on the heap is not a great idea IMO. Optimize your application instead.

Upvotes: 1

Cowan
Cowan

Reputation: 37543

Something like what you're after is built into recent JVMs.

If you:

  • are using Hotspot VM from (at least) Java 6
  • are using the Parallel or Concurrent garbage collectors
  • have the option UseGCOverheadLimit enabled (it's on by default with those collectors, so more specifically if you haven't disabled it)

then you will get an OOM before actually running out of memory: if more than 98% of recent time has been spent in GC for recovery of <2% of the heap size, you'll get a preemptive OOM.

Tuning these parameters (the 98% in particular) sounds like it would be useful to you, however there is no way as far as I'm aware to tune those thresholds.

However, check that you qualify under the three points above; if you're not using those collectors with that flag, this may help your situation.

It's worth reading the HotSpot JVM tuning guide, which can be a big help with this stuff.

Upvotes: 8

NPE
NPE

Reputation: 500357

I am not aware of any way to configure the Java garbage collector in the manner you describe.

One way might be for your application to proactively monitor the amount of free memory, e.g. using Runtime.freeMemory(), and declare the "I'm dead" condition if that drops below a certain threshold and can't be rectified with a forced garbage collection cycle.

The idea is to pick the value for the threshold that's large enough for the process to never get into the situation you describe.

Upvotes: 2

Related Questions