0
votes

My java application which uses JNI is crashing with hs_err_pid file giving the error as "Exception Access Violation". The OS is Windows VISTA.

From what I know, my native code is illegally writing to some chunk of memory that does not belong to it.

I have used valgrind on Linux on pure native code to detect such problems in the past.

But when using java, valgrind simply fails and does not work.

What (if any) method would you suggest to identify the offending piece of code?

It is not possible for me to manually dig through the native code (few million lines) to identify it.

3
Can you run/test the native code as a stand alone library without using Java? - Peter Lawrey
Good suggestion. Thats why I had been thinking of. Using is from a C/C++ program would however require considerable time and effort. I will resort to it if I do not find a reliable way of identifying it from my java app. - Santosh Tiwari
Debugging a random crash in a large C/C++ is hard enough, trying to debug it through Java is like trying to debug with your eyes closed. ;) - Peter Lawrey
If you're using the MS compiler, you can put a try { } catch(...) { } around your JNI call and throw a java exception from the catch. That at least prevents you from crashing and lets you view the Java context around the call. You can use SEH with GCC, too, it's just a little more tricky, and only available on 32-bit. - technomage
You should be able to attach the running java process with gdb (if using gcc) or the MS visual studio debugger (if using MSVC). In either case, once attached you should be able to debug the native code normally. - technomage

3 Answers

4
votes

I was finally able to resolve the issue. I thought I will post the procedure here in case someone else is in a similar situation.

Step 1: Build the native code with proper debugging symbols. The compiler flags could be something like

"-g -rdynamic -O0"

Step 2: The following valgrind command should do the job.


valgrind --error-limit=no --trace-children=yes --smc-check=all --leak-check=full --track-origins=yes -v $JAVA -XX:UseSSE=0 -Djava.compiler=NONE $JAVA_ARGS

In the above command, $JAVA is the java executable and $JAVA_ARGS is the arguments to your java program.

Once successfully started, it will take orders of magnitude more time to complete the execution. Valgrind will print thousands of errors (most related to jvm which can be ignored). You can however identify the ones that relate to your jni code.

This general strategy should be applicable to most native memory related problems.

2
votes

If you are running Java under Linux, you could use the -XX:OnError="gdb - %p" option to run gdb when the error occurs. See this example.

Under windows, you can use the -XX:+UseOSErrorReporting option to obtain a similar effect.

0
votes

For debugging JNI code a method posted in this article could be useful (it's about debugging JNI using Netbeans and Visual Studio). It's simple - just start your Java program, then in Visual Studio pick Debug -> Attach to process and choose java.exe process running your program.

When you add breakpoints to your C++ code, Visual Studio will break on them. Voila :)