When designing an application that is made up of Java and Native code it is important to handle signals correctly. What I’m trying to say is that JVM uses signals internally and if your application registers itself as a signal handler it will intercept signals intended for JVM. As a result JVM’s signal handler will not be invoked. Eventually this will lead to incorrect behavior and most likely a JVM crash.
Don’t worry Sun provides an excellent signal chaining library that makes solving this problem very easy. Let’s elaborate on this a bit.
First thing first, what are signals?
First of all, lets make sure we are on the same page about signals. As stated in wikipedia “A signal is a limited form of inter-process communication used in Unix, Unix-like, and other POSIX-compliant operating systems.” See http://en.wikipedia.org/wiki/Signal_%28computing%29
Problem Description
Solaris and Linux JVMs use signals internally. This means that the JVM will originate signals and it will need to handle them. The problem arises when native code registers itself as a signal handler following JVMs initialization. Since there can be only one signal handler for a particular signal, the native code signal handler will overwrite JVMs signal handler. When this happens, every time JVM originates a signal, the signal will be intercepted by the native code signal handler. As a result JVM signal handler will neverget invoked. This can lead to the unexplained behavior that is very difficult to debug.

Example
Check the attached sample code for example. In this example, the C++ file creates a JVM and registers a signal handler immediately after. This will override JVMs signal handler. If you let this program run you will witness a JVM crash. JVMs will originate signals, its signal handler will never get invoked and the problem will never get addressed. Tested on Ubuntu linux with Java 1.6.
To compile Java:
javac *.java
jar cvf testJNI.jar *.class
To compile and link native code:
g++ -c -I /usr/lib/jvm/java-6-sun-1.6.0.03/include/ -I /usr/lib/jvm/java-6-sun-1.6.0.03/include/linux -o ../bin/jnitest.o testjni.cpp
g++ ../bin/jnitest.o -L /usr/lib/jvm/java-6-sun-1.6.0.03/jre/lib/i386/client
-ljvm -o ../bin/jnitest.x
Solutions
It turns out that the solution is incredibly simple. In fact this problem can be solved three different ways:
-
remove signal handlers from your native code.
-
recompile with signal chaining library.
-
set LD_PRELOAD env. variable prior to launching the program.

Signal Chaining
Using signal chaining requires no code modification and is explained here:
http://java.sun.com/j2se/1.4.2/docs/guide/vm/signal-chaining.html
How to fix Example above.
Fortunately there is a fine signal chaining library provided for free by SunTM.
Here is how I linked the attached sample code and enabled signal chaining. The part in red is needed to enable the signal chaining, which solves the problem. Java code does not need to be recompiled.
g++ -c -I /usr/lib/jvm/java-6-sun-1.6.0.03/include/ -I /usr/lib/jvm/java-6-sun-1.6.0.03/include/linux -o ../bin/jnitest.o testjni.cpp
g++ ../bin/jnitest.o -L /usr/lib/jvm/java-6-sun-1.6.0.03/jre/lib/i386/client-ljsig -ljvm -o ../bin/jnitest.x
Any questions, let me know.
Best description on the web. I’m amazed how simple the solution is! This should be better advertised on the sun’s web site.
void mySigHandler( int sig ){
printf(“mySigHandler received signal: %d \n”, sig );
signal(SIGINT, mySigHandler);—> This does not look right rest understandable
}
signal(SIGINT, mySigHandler); <– will register mySigHandler function as a handler for SIGINT. I believe on some platforms you may need to re-register your signal handler or the default handler will be invoked with the next SIGINT.
Clear and Concise! Excellent Work..
3 questions.
1) signal(SIGINT,mySigHandler) or simply using signal from handler function seems not allowed by g++ compiler … any idea why ?
2) how does signal chaining help for handling native code related issues which can raise signal ?
3) can we have more insight on 3rd approach of using LD_PRELOAD?
You are a pioneer my friend. Thanks for paving the way to a proof my code is not the culprit of the JVM crash.
Mehul,
just got back from my vacation. Let me try to answer your questions.
1. signal(SIGINT,mySigHandler) or simply using signal from handler function seems not allowed by g++ compiler … any idea why ?
> I’m not sure what you mean. Did you include the signal.h? see included sample below.
2. how does signal chaining help for handling native code related issues which can raise signal ?
>If the native code uses signals and creates the JVM, the JVM will override the signal handler in the native code. The signal chaining allows JVM to determine whether a raised signal was intended for it.
I believe that in native code, if two or more libraries use the same signals it is possible that at least one of the signal handlers will be overridden. Thus signal chaining can be used to ensure that the signals are properly dispatched to the right handlers. If I’m correct, it can be done by first loading a library that will store signal handlers when libraries register their signal handlers. It will then dispatch signals to the right signals handlers. This means that the dispatching library must be loaded first, before libraries that implement signal handlers are loaded.
Here is an example (jsig.c) implementation.
http://xref.jsecurity.net/openjdk-6/langtools/d3/dae/solaris_2vm_2jsig_8c-source.html
3. can we have more insight on 3rd approach of using LD_PRELOAD?
>LD_PRELOAD simply specifies libraries that must be loaded before other libraries are loaded. This avoids a need to link with the library that stores and dispatches to the signal handlers.
Signal example:
———————————————–
#include
#include
#include
void handler( int sig ){
printf(“signal handler invoked, signal: %d \n”, sig );
}
int main(){
signal( SIGINT, handler );
printf(“test SIGINT\n”);
while( 1 ){
sleep(1000);
}
return 1;
}
Hi,
what is the use of CheckJni flag?. If we dont set it in our code, then native singals still collide with JVM signals?
[...] http://javajiggle.com/2008/01/06/if-jni-based-application-is-crashing-check-signal-handling/ [...]
[...] JavaJiggle Article on Signal Handling [...]