Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error with jni (java6) and X25 native code (C language) when code uses system call "connect()" on Solaris 5.9

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.

like image 490
aoe Avatar asked Nov 13 '22 07:11

aoe


1 Answers

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

like image 131
aoe Avatar answered Nov 16 '22 02:11

aoe