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]

# 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?
# 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