In past years, we created a program that uses X25 protocol. It was made in C language and works fine for a Sun-Fire machine with Solaris 5.9.
Recently, we are working with java 6 in same machine, and we are trying to adapt that old program in C for working with java via jni.
So I have done some modifications to the old C program and created a shared library named x25lib.so
But I have found a runtime problem using jni and X25: When the C function is invoked from java via jni, the C code does not work in a same way that when it is invoked from another C program.
Concrete, using jni, the C code in shared library works fine until is invoked the system call connect()
, then returns -1,
But invoking the same C code of my shared library from another C program returns 0 (ok)
In both cases, the C code in shared library doesn´t receive external parameters so the conditions are the same, I don´t understand if loading my "x25lib.so" shared library from java have a little difference that induce connect()
in C fails.
using "truss" command from java I have found the error:
/2: connect(5, 0xFD878B75, 112, 1) Err#22 EINVAL
the same, but invoking the shared lib from another C program:
connect(4, 0xFFBFE794, 114, 1) = 0
So it works ok only with pure C,
Is there another consideration for using jni and X25 for solaris 5.9?
IMPORTANT: C Code in shared library is identical in both cases.
COMPILATION TIME:
a. Creating x25lib.so
cc -w -fd -G -Kpic subs.o -L/opt/SUNWconn/lib -R/opt/SUNWconn/lib -lsockx25
-lsocket -lnsl -I"/SDK/jdk/include/" -I"/SDK/jdk/include/solaris/"
-o x25lib.so -h x25lib.so x25jni.c
b. Creating a test C program with that shared library:
cc -w x25lib.so -o x25test x25test.c
where `x25test.c` contains:
#include <stdio.h>
main()
{
java_x25();
}
c. Using java:
public class X25 {
static {
System.load("/home/x25lib.so");
}
public native void ejecutaComando();
}
public class TestX25 {
public static void main(String ... args) {
X25 x25 = new X25();
x25.ejecutaComando();
}
}
Then in C code shared library:
/*
* Class: X25
* Method: ejecutaComando
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_X25_ejecutaComando
(JNIEnv *env, jobject obj)
{
java_x25();
}
So finally both programs (java y C) call exactly the same C code in shared library:
java_x25()
Without parameters, so execute the same code.
Why works fine when is called from C, but fails when is called from java?
Thanks for any advice.
Thanks for your comments. I have found a solution while I was trying another approach: I decided not using jni, instead I adapted the old C program for listening for simple tcp connections from java and then could execute x25 code, but surprise, I got the same runtime error like using jni:
connect(5, 0xFD8789C5, 112, 1) Err#22 EINVAL
including a size of 112 instead 114, it was the same problem.
So I noticed that the problem was that I had compiled the new C program with "-lsocket" option before "-lsockx25", so that was a clue. Then I searched in google and I found a similar problem:
link to java X25 Bug ID:4077576
At the end of that article, it is mentioned the option LD_PRELOAD to force sockx25 library be loaded first. Finally the solution was at runtime:
bash$ export LD_PRELOAD=/opt/SUNWconn/lib/libsockx25.so
bash$ java TestX25
and then all is working fine using jni.
Reference for LD_PRELOAD: link to java tuning
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