From IBM:
-Xrs
Disables signal handling in the JVM.
-Xrs
Setting -Xrs prevents the Java™ run time environment from handling any internally or externally generated signals such as SIGSEGV and SIGABRT. Any signals that are raised are handled by the default operating system handlers. Disabling signal handling in the JVM reduces performance by approximately 2-4%, depending on the application.
-Xrs:sync
On UNIX systems, this option disables signal handling in the JVM for SIGSEGV, SIGFPE, SIGBUS, SIGILL, SIGTRAP, andSIGABRT signals. However, the JVM still handles the SIGQUIT and SIGTERM signals, among others. As with -Xrs, the use of -Xrs:sync reduces performance by approximately 2-4%, depending on the application.
Note: Setting this option prevents dumps being generated by the JVM for signals such as SIGSEGV and SIGABRT, because the JVM is no longer intercepting these signals.
https://www-01.ibm.com/support/knowledgecenter/SSYKE2_7.0.0/com.ibm.java.aix.70.doc/diag/appendixes/cmdline/Xrs.html
From my understanding, -Xrs
is really used to prevent dumps from being generated when certain OS Signals are intercepted.
Since the JVM is no longer intercepting and handling these signals, it would stand to reason this would increase performance, not decrease it as claimed by IBM.
Why does -Xrs
reduce performance?
Because of safepoints and VM operations, as well as other optimizations that the JIT can do if you allow it to manage signals.
The JVM occasionally has to perform some operations that require it to pause execution globally ("stop the world"), such as certain large-scale garbage collection, hot reloading or internally recompiling classes, and the like. In order to do this, it has to make sure that all running threads hit a barrier and pause at the same time, do the operation, and then release the threads.
One technique that HotSpot (and likely other JVMs) uses to implement safepoints is a clever abuse of segfaults: It sets up a memory page that is not actually used for any data, and then each thread periodically tries to read from that page. When no VM operation is required, the read succeeds with very low overhead and the thread just keeps running.
When the JVM does need to perform a VM operation, it invalidates that memory page. The next time each thread hits a safepoint, it now causes a segfault, which lets the JVM regain control of that thread's execution; it holds until the VM operation is done, resets the sentinel page, and restarts all the threads.
When you disable SIGSEGV handling, the JVM has to use other techniques to synchronize safepoints that are less efficient than delegating to the processor's built-in memory protection.
Additionally, the JVM does some serious magic with profiling (essentially similar to a CPU's branch predictor). One of the optimizations it uses is that if it detects that a certain null check is almost never null, it elides the check and relies on a segfault (expensive, but in such a case rare) to catch the null. This optimization also requires custom handling of SIGSEGV.
In addition to safepoints mentioned by @chrylis segfault handlers are also used for other clever optimization tricks such as implicit null pointer checking (at least they're on hotspot). If profiles show that a null-checking code path is rarely triggered it's optimized out and the unlikely case is then covered by the signal handler instead.
Such an optimization cannot be performed without installing a custom signal handler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With