This chapter provides information on how signals and exceptions are handled by the Java HotSpot Virtual Machine. It also describes the signal chaining facility, available on Solaris OS and Linux, that facilitates writing applications that need to install their own signal handlers.
This chapter contains the following sections:
The Java HotSpot VM installs signal handlers to implement various features and to handle fatal error conditions. For example, in an optimization to avoid explicit null checks in cases where java.lang.NullPointerException
will be thrown rarely, the SIGSEGV
signal is caught and handled, and the NullPointerException
is thrown.
In general there are two categories of situations where signal/traps arise:
When signals are expected and handled, like the implicit null-handling cited above. Another example is the safepoint polling mechanism, which protects a page in memory when a safepoint is required. Any thread that accesses that page causes a SIGSEGV
, which results in the execution of a stub that brings the thread to a safepoint.
Unexpected signals. This includes a SIGSEGV
when executing in VM code, Java Native Interface (JNI) code, or native code. In these cases the signal is unexpected, so fatal error handling is invoked to create the error log and terminate the process.
The following table lists the signals that are currently used on Solaris OS and Linux.
Table 6-1 Signals Used on Solaris OS and Linux
Signal | Description |
---|---|
|
These signals are used in the implementation for implicit null check, and so forth. |
|
This signal is used to dump Java stack traces to the standard error stream. (Optional) |
|
These signals are used to support the shutdown hook mechanism ( |
|
This signal is used in the implementation of the |
|
This signal is used internally. Not used starting with Solaris 10 OS. (Configurable) |
|
The HotSpot VM does not handle this signal. Instead it calls the |
Signals tagged as "optional" are not used when the -Xrs
option is specified to reduce signal usage. With this option fewer signals are used, although the VM installs its own signal handler for essential signals such as SIGSEGV
. Specifying this option means that the shutdown hook mechanism will not execute if the process receives a SIGQUIT
, SIGTERM
, SIGINT
, or SIGHUP
. Shutdown hooks will execute, as expected, if the VM terminates normally (that is, when the last non-daemon thread completes or the System.exit
method is invoked).
On Solaris 8 and 9 OS, signals tagged as "configurable" are substituted when the -XX:+UseAltSigs
option is specified to use alternative signals. Starting with Solaris 10 OS, this option is ignored, as the operating system reserves two additional signals (called SIGJVM1
and SIGJVM2
).
On Linux, the handler for SIGUSR1
cannot be overridden. SIGUSR2
is used to implement suspend and resume. However it is possible to specify an alternative signal to be used instead of SIGUSR2
. This is done by specifying the _JAVA_SR_SIGNUM
environment variable. If this environment variable is set, it must be set to a value larger than the maximum of SIGSEGV
and SIGBUS
.
If an application with native code requires its own signal handlers, then it might need to be used with the signal chaining facility. The signal chaining facility offers the following features:
Support for pre-installed signal handlers when the HotSpot VM is created.
When the VM is first created, existing signal handlers (that is, handlers for signals that are used by the VM) are saved. During execution, when any of these signals are raised and found not to be targeted at the Java HotSpot VM, the pre-installed handlers are invoked. In other words, pre-installed handlers are chained behind the VM handlers for these signals.
Support for signal handler installation after the HotSpot VM is created, either inside JNI code or from another native thread.
An application can link and load the libjsig.so shared library before libc/libthread/libpthread. This library ensures that calls such as signal()
, sigset()
, and sigaction()
are intercepted so that they do not actually replace the Java HotSpot VM's signal handlers if the handlers conflict with those already installed by the VM. Instead, these calls save the new signal handlers (or chain them behind the VM-installed handlers). During execution, when any of these signals are raised and found not to be targeted at the Java HotSpot VM, the pre-installed handlers are invoked.
If support for signal handler installation after the creation of the VM is not required, then the libjsig.so shared library is not needed.
Perform one of these two procedures to use the libjsig.so shared library:
Link it with the application that creates/embeds the HotSpot VM:
cc -L libjvm.so-directory -ljsig -ljvm java_application.c
Use the LD_PRELOAD
environment variable:
KornShell (ksh):
export LD_PRELOAD=libjvm.so-directory/libjsig.so; java_application(ksh)
C shell (csh):
setenv LD_PRELOAD libjvm.so-directory/libjsig.so; java_application(csh)
The interposed signal()
, sigset()
, and sigaction()
return the saved signal handlers, not the signal handlers installed by the Java HotSpot VM and which are seen by the operating system.
Note that SIGUSR1
cannot be chained. If an application attempts to chain this signal on Solaris OS, then the HotSpot VM terminates with the following fatal error:
Signal chaining detected for VM interrupt signal, try -XX:+UseAltSigs
Also, the SIGQUIT
, SIGTERM
, SIGINT
, and SIGHUP
signals cannot be chained. If the application needs to handle these signals, consider using the -Xrs
option.
On Solaris OS, the SIGUSR2
signal can be chained only for non-Java and non-VM threads (that is, it can only be used for native threads created by applications that do not attach to the VM).
On Windows, an exception is an event that occurs during the execution of a program. There are two kinds of exceptions: hardware exceptions and software exceptions. Hardware exceptions are comparable to signals such as SIGSEGV
and SIGKILL
on Solaris OS and Linux. Software exceptions are initiated explicitly by applications or the operating system using the RaiseException()
API.
On Windows, the mechanism for handling both hardware and software exceptions is called structured exception handling (SEH). This is stack frame-based exception handling similar to the C++ and Java exception handling mechanism. In C++ the __try
and __except
keywords are used to guard a section of code that might result in an exception, as in the following example:
__try {
// guarded body of code
} __except (filter-expression) {
// exception-handler block
}
The __except
block is filtered by a filter expression that uses the integer exception code returned by the GetExceptionCode()
API, exception information returned by the GetExceptionInformation()
API, or both.
The filter expression should evaluate to one of the following values:
EXCEPTION_CONTINUE_EXECUTION = -1
The filter expression has repaired the situation, and execution continues where the exception occurred. Unlike some exception schemes, SEH supports the resumption model as well. This is much like Unix signal handling in the sense that after the signal handler finishes, the execution continues where the program was interrupted. The difference is that the handler in this case is just the filter expression itself and not the __except
block. However, the filter expression might also involve a function call.
EXCEPTION_CONTINUE_SEARCH = 0
The current handler cannot handle this exception. Continue the handler search for the next handler. This is similar to the catch
block not matching an exception type in C++ and Java.
EXCEPTION_EXECUTE_HANDLER = 1
The current handler matches and can handle the exception. The __except
block is executed.
The __try
and __finally
keywords are used to construct a termination handler as follows
__try { // guarded body of code } __finally { // __finally block }
When control leaves the __try
block (after exception or without exception), the __finally
block is executed. Inside the __finally
block, the AbnormalTermination()
API can be called to test whether control continued after the exception or not.
Windows programs can also install a top-level unhandled exception filter function to catch exceptions that are not handled in the __try
/__except
block. This function is installed on a process-wide basis using the SetUnhandledExceptionFilter()
API. If there is no handler for an exception, then UnhandledExceptionFilter()
is called, and this will call the top-level unhandled exception filter function, if any, to catch that exception. This function also shows a message box to notify the user about the unhandled exception.
Windows exceptions are comparable to Unix synchronous signals that are attributable to the current execution stream. In Windows, asynchronous events such as console events (for example, the user pressing Control+C at the console) are handled by the console control handler registered using the SetConsoleCtlHandler()
API.
If an application uses the signal()
API on Windows, then the C runtime library (CRT) maps both Windows exceptions and console events to appropriate signals or C runtime errors. For example, CRT maps Control+C to SIGINT
and all other console events to SIGBREAK
. Similarly, if you register the SIGSEGV
handler, CRT translates the corresponding exception to a signal. CRT startup code implements a __try
/__except
block around the main()
function. The CRT's exception filter function (named _XcptFilter
) maps the Win32 exceptions to signals and dispatches signals to their appropriate handlers. If a signal's handler is set to SIG_DFL
(default handling), then _XcptFilter
calls UnhandledExceptionFilter
.
With Windows XP or Windows 2003, the vectored exception handling mechanism can also be used. Vectored handlers are not frame-based handlers. A program can register zero or more vectored exception handlers using the AddVectoredExceptionHandler
API. Vectored handlers are invoked before structured exception handlers, if any, are invoked, regardless of where the exception occurred.
Vectored exception handler returns one of the following values:
EXCEPTION_CONTINUE_EXECUTION
: Skip next vectored and SEH handlers.
EXCEPTION_CONTINUE_SEARCH
: Continue next vectored or SEH handler.
Refer to the Microsoft web site at http://www.microsoft.com
for further information on Windows exception handling.
The HotSpot VM installs a top-level exception handler during initialization using the SetUnhandledExceptionFilter
API for 32-bit systems, or the AddVectoredExceptionHandler
API for 64-bit systems.
It also installs the win32 SEH using a __try
/__except
block in C++ around the thread (internal) start function call for each thread created.
Finally, it installs an exception handler around JNI functions.
If an application must handle structured exceptions in JNI code, it can use __try
/__except
statements in C++. However, if it must use the vectored exception handler in JNI code then the handler must return EXCEPTION_CONTINUE_SEARCH
to continue to the VM's exception handler.
In general, there are two categories of situations in which exceptions arise:
When exceptions are expected and handled. Examples include the implicit null handling cited above where accessing a null causes an EXCEPTION_ACCESS_VIOLATION
, which is handled.
Unexpected exceptions. An example is an EXCEPTION_ACCESS_VIOLATION
when executing in VM code, or in JNI code, or in native code. In these cases the signal is unexpected, and fatal error handling is invoked to create the error log and terminate the process.
The Java HotSpot VM registers console events as shown in the following table.
Table 6-2 Console Events
Console Event | Signal | Usage |
---|---|---|
|
|
This event and signal is used to terminate a process. (Optional) |
|
|
This event and signal is used by the shutdown hook mechanism when the VM is terminated abnormally. (Optional) |
|
|
This event and signal is used to dump Java stack traces at the standard error stream. (Optional) |
If an application must register its own console handler, then the -Xrs
option can be used. With this option, shutdown hooks are not run on SIGTERM
(with above mapping of events) and thread dump support is not available on SIGBREAK
(with above mapping of the Control+Break event).