Fatal errors and the -XX:OnError= option in the HotSpot VM

http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp says that the

-XX:OnError="<cmd args>;<cmd args>"

option runs "user-defined commands on fatal error".

What is considered a "fatal error"? Are OutOfMemoryErrors included in this category? (So that if I set -XX:OnError, I won't also have to set -XX:OnOutOfMemoryError?)

Also, does anyone know why these options weren't backported to 1.5?

Thanks!

[457 byte] By [EmboMana] at [2007-11-26 20:52:29]
# 1
I have experimented a little, and the results indicate that OutOfMemoryErrors are not "fatal errors". So what kind of errors are fatal errors?
EmboMana at 2007-7-10 2:17:57 > top of Java-index,Core,Monitoring & Management...
# 2
A fatal error would be unhandled exception or signal from the operating system (think crash). An OutOfMemoryError is not fatal. Are you looking to have something executed when OOME is thrown?
alan.batemana at 2007-7-10 2:17:57 > top of Java-index,Core,Monitoring & Management...
# 3
OK, thanks...I plan to execute a shell script for notifying users/admins when such errors occur. I'll go ahead and set both the -XX:OnError and -XX:OnOutOfMemoryError options, then.
EmboMana at 2007-7-10 2:17:57 > top of Java-index,Core,Monitoring & Management...
# 4
Is it possible to start some shell command on OutOfMemory in JDK 1.5? The main goal is to kill JVM process, or at least inform system administrator somehow...
Konstantin.Krivopustova at 2007-7-10 2:17:57 > top of Java-index,Core,Monitoring & Management...
# 5

I've the same problem: we have used the option -XX:OnOutOfMemoryError to run a shell script to kill the JVM, migrating to jvm 1.5 we have found that this option has not ported yet to this version.

We cannot upgrade to jvm 1.6 on a production environment without doing a strong test our application.

Anyone knowns if it is planned to port this option also in jvm 1.5?

Any idea to obtain the same goal in another way, other then fill our code with some code like this:

try {...} catch (OutOfMemoryException e) {System.exit(-1);} ?

da502548a at 2007-7-10 2:17:57 > top of Java-index,Core,Monitoring & Management...
# 6
I do not think there is any plan to port this option to 1.5. You can use the runtime.exec API from java code to run shell command: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Runtime.html#exec(java.lang.String)
swamyva at 2007-7-10 2:17:57 > top of Java-index,Core,Monitoring & Management...
# 7
Why is this feature (OnOutOfMemoryError) in 1.4.2 and 1.6, but not 1.5? It seems really strange.
dalangalmaa at 2007-7-10 2:17:57 > top of Java-index,Core,Monitoring & Management...
# 8

This feature has been introduced with java version 6 and it has been back-ported to the release 12 of the 1.4.2 near at the same time. (late 2006 if I'm not wrong)

I agree with you that it's very strange to leave the 1.5 without this useful option, especially for server applications.

Anyone know if there is a place where we can suggest this feature for the next release of the java 1.5? (something like "vote the bug")

da502548a at 2007-7-10 2:17:57 > top of Java-index,Core,Monitoring & Management...
# 9

I've found a workaround to get a similar beahviour usign the option -XX:+HeapDumpOnOutOfMemoryError

If this option is active when the jvm goues runs OutOfMemory a dump is written to the file specified with the option -XX:HeapDumpPath=filename

You can so run a bash script that periodically check the presence of the dump file and if found kill the jvm.

Here an example of the script I've created:

OOMDUMPFILE="filename" ; if test -f $OOMDUMPFILE ;

then rm $OOMDUMPFILE ; fi ; (java -XX:HeapDumpPath=filename

-XX:+HeapDumpOnOutOfMemoryError -cp myjar.jar &) &&

(while (true) ; do if test -f $OOMDUMPFILE ; then echo "OutOfMemory detected"

; killall -SIGKILL java ; exit 0 ; else echo "debug: sleeping ..." ; sleep 1 ; fi ;

done)

The echo "debug: sleeping ..." can be removed, it can be used only to test the script.

To be test that the jvm will be killed try to reduce the memory available to a very low value.

NOTE: the command killall -SIGKILL java

will kill all java commands runned by the logged user, if you run more than one java process with that user you should find the PID to kill

Another way I'm investigating is to use jmx notification, I'm studying the possibility to get notifications from the MemoryMXBean but I need some other time to study this possibility

Has anyone already tried this possibility?

da502548a at 2007-7-10 2:17:57 > top of Java-index,Core,Monitoring & Management...
# 10

Hello all, I'm here again.

Investigating about java jmx and management functionalities, I've found this article http://www.theserverside.com/news/thread.tss?thread_id=27481 that I've used as a starting point to create a simple shutdown class that will be called if the jvm runs out of memory.

This approach is not the best due to impossibility for the jvm to really complete the execution of running threads when out of memory occours.

For example I've tested some situations were the jvm doesn't exit, especially if the OutOfMemoryError is thrown for saturation of the permanent generation memory pool.

This may be explained as the impossibility for the jvm to load all the necessary bytecode to execute.

import java.lang.management.ManagementFactory;

import java.lang.management.MemoryMXBean;

import java.lang.management.MemoryNotificationInfo;

import java.lang.management.MemoryPoolMXBean;

import java.lang.management.MemoryUsage;

import javax.management.ListenerNotFoundException;

import javax.management.Notification;

import javax.management.NotificationBroadcaster;

import javax.management.NotificationListener;

import javax.management.openmbean.CompositeData;

public class ExitOnOutOfMemoryError {

private static boolean active = false;

private static final NotificationListener listener = new NotificationListener() {

public void handleNotification(Notification notification, Object handback) {

if (MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED.equals(notification.getType())) {

CompositeData cd = (CompositeData) notification.getUserData();

MemoryNotificationInfo info = MemoryNotificationInfo.from(cd);

System.out.println("OUT OF MEMORY ERROR ON " + info.getPoolName());

System.err.println("OUT OF MEMORY ERROR ON " + info.getPoolName());

System.exit(-1);

}

}

};

public static void setActive(boolean active) {

if (ExitOnOutOfMemoryError.active == active) return;

MemoryMXBean mem = ManagementFactory.getMemoryMXBean();

if (active) {

((NotificationBroadcaster) mem).addNotificationListener(listener, null, null);

for (MemoryPoolMXBean memPool : ManagementFactory.getMemoryPoolMXBeans()) {

if (memPool.isUsageThresholdSupported()) {

MemoryUsage memUsage = memPool.getUsage();

long max = memUsage.getMax();

double percentage = 1;

memPool.setUsageThreshold((long) (max * percentage));

}

}

System.out.println("ExitOnOutOfMemoryError enabled");

}

else {

try {

((NotificationBroadcaster) mem).removeNotificationListener(listener);

System.out.println("ExitOnOutOfMemoryError disabled");

} catch (ListenerNotFoundException e) {

e.printStackTrace();

}

}

ExitOnOutOfMemoryError.active = active;

}

}

P.S. IMHO is conceptually wrong to run the controller and controlled on the same environment, the first solution I propose it is really more robust

Message was edited by:

da502548

da502548a at 2007-7-10 2:17:57 > top of Java-index,Core,Monitoring & Management...