java jni solaris

Error con jni(java6) y código nativo X25(lenguaje C) cuando el código usa la llamada al sistema "connect()" en Solaris 5.9



(2)

En años anteriores, creamos un programa que usa el protocolo X25. Fue hecho en lenguaje C y funciona bien para una máquina Sun-Fire con Solaris 5.9. Recientemente, estamos trabajando con Java 6 en la misma máquina, y estamos tratando de adaptar ese viejo programa en C para trabajar con Java a través de jni. Así que hice algunas modificaciones al antiguo programa C y creé una biblioteca compartida llamada x25lib.so

Pero he encontrado un problema de tiempo de ejecución con jni y X25: cuando la función C se invoca desde java a través de jni, el código C no funciona de la misma manera que cuando se invoca desde otro programa C.

Concreto, usando jni, el código C en la biblioteca compartida funciona bien hasta que se invoca la llamada al sistema connect() , luego devuelve -1,

Pero al invocar el mismo código C de mi biblioteca compartida de otro programa C, devuelve 0 (ok)

En ambos casos, el código C de la biblioteca compartida no recibe parámetros externos, por lo que las condiciones son las mismas, no entiendo si la carga de mi biblioteca compartida "x25lib.so" de Java tiene una pequeña diferencia que induce connect() en C falla

usando el comando "truss" de Java, he encontrado el error:

/2: connect(5, 0xFD878B75, 112, 1) Err#22 EINVAL

lo mismo, pero invocando la biblioteca compartida de otro programa C:

connect(4, 0xFFBFE794, 114, 1) = 0

Entonces funciona bien solo con C puro

¿Hay alguna otra consideración para usar jni y X25 para Solaris 5.9?

IMPORTANTE: el código C en la biblioteca compartida es idéntico en ambos casos.

TIEMPO DE COMPILACIÓN:

a. Creando 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

segundo. Creando un programa C de prueba con esa biblioteca compartida:

cc -w x25lib.so -o x25test x25test.c where `x25test.c` contains: #include <stdio.h> main() { java_x25(); }

do. Usando 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(); } }

Luego, en la biblioteca compartida de código C:

/* * Class: X25 * Method: ejecutaComando * Signature: ()V */ JNIEXPORT void JNICALL Java_X25_ejecutaComando (JNIEnv *env, jobject obj) { java_x25(); }

Entonces, finalmente, ambos programas (java y C) llaman exactamente el mismo código C en la biblioteca compartida:

java_x25 ()
Sin parámetros, así que ejecuta el mismo código.

¿Por qué funciona bien cuando se llama desde C, pero falla cuando se llama desde Java?

Gracias por cualquier consejo.


Algunas observaciones (publique su código si desea que profundicemos en esto, en particular la parte que configura los parámetros para connect() ):

Suponiendo X.25 sobre TCP (?):

  1. Desde la página man EINVAL se devuelve desde connect(3socket) "namelen no es el tamaño de una dirección válida para la familia de direcciones especificada" donde namelen es la estructura namelen definida en <sys/socket_impl.h> . namelen es típicamente 16 (una familia de direcciones de 2 bytes (esperaría SOCK_STREAM ) seguido de 14 octetos de datos de direcciones). Su programa devuelve namelen 112 o 114.

  2. La dirección del name en la salida de su truss(1) falsa truss(1) encima de 0xFD878B75 es impar (impar en el sentido "ni siquiera"). Teniendo en cuenta los requisitos de alineación típicos de Solaris, esto parece extraño. (SPARC o x86? ¿Qué compilador y banderas?). Tal vez un puntero o tamaño de problema?

  3. Desde su truss(1) salida puede ver que los hilos se están utilizando en la invocación java. ¿Tus bibliotecas son seguras para hilos?


Gracias por tus comentarios. Encontré una solución mientras intentaba otro enfoque: decidí no usar jni, en su lugar, adapté el antiguo programa C para escuchar conexiones simples de TCP de Java y luego pude ejecutar código x25, pero sorpresa, obtuve el mismo error de tiempo de ejecución como usando jni:

connect(5, 0xFD8789C5, 112, 1) Err#22 EINVAL

incluyendo un tamaño de 112 en lugar de 114, fue el mismo problema.

Entonces noté que el problema era que había compilado el nuevo programa C con la opción "-lsocket" antes de "-lsockx25" , así que eso era una pista. Luego busqué en Google y encontré un problema similar:

enlace a java X25 ID de error: 4077576

Al final de ese artículo, se menciona la opción LD_PRELOAD para forzar que la biblioteca sockx25 se cargue primero. Finalmente la solución fue en tiempo de ejecución:

bash$ export LD_PRELOAD=/opt/SUNWconn/lib/libsockx25.so

bash$ java TestX25

y luego todo está funcionando bien usando jni.

Referencia para LD_PRELOAD: enlace al ajuste de java