2012-04-10 7 views
5

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 han hecho algunas modificaciones en el antiguo programa C y creó una biblioteca compartida llamada x25lib.soError con jni (java6) y código nativo X25 (lenguaje C) cuando el código usa la llamada al sistema "connect()" en Solaris 5.9

pero he encontrado un problema de tiempo de ejecución usando JNI y X25: Cuando la función C se invoca desde Java a través de JNI, el código C hace no funciona de la misma manera que cuando se invoca desde otro programa C.

hormigón, utilizando JNI, el código C en la biblioteca compartida funciona bien hasta que se invoca la llamada al sistema connect(), a continuación, devuelve -1,

Pero invocando el mismo código C de mi biblioteca compartida desde otro programa de C devuelve 0 (ok)

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

el uso de "armadura" de comandos de java he encontrado el error:

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

la misma, pero la invocación de la librería compartida de otro programa C:

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

por lo que funciona bien sólo pure C,

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

IMPORTANTE: C El código 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 

b. Creación de 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(); 
    } 

c. Utilización de 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(); 
    } 

} 

biblioteca Luego, en el código C compartida:

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

     java_x25(); 

} 

por lo que finalmente ambos programas (Java y C) llame exactamente la misma C código en la biblioteca compartida:

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

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

Gracias por cualquier consejo.

+0

¿Seguro de código independiente de su 'C' es idéntica a su código JNI? – EJP

+0

Gracias por su respuesta EJP. Sí, el código es idéntico, esa es mi frustación.Edito mi pregunta y agrego el código jni donde se puede ver que se invoca el mismo código que en el código C independiente. – aoe

Respuesta

0

Algunas observaciones (por favor publicar su código si desea que vayamos más profundo en esto - en particular la parte que establece los parámetros para connect()):

Suponiendo X.25 sobre TCP (?):

  1. desde la página del 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 sockaddr definido 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 dirección). Su programa vuelve namelen 112 o 114.

  2. La dirección de name en su truss(1) de salida no superior 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 salida truss(1) puede ver que los hilos se están utilizando en la invocación java. ¿Tus bibliotecas son seguras para hilos?

1

Gracias por sus comentarios. Encontré una solución mientras intentaba otro enfoque: decidí no usar jni, en cambio adapté el viejo programa C para escuchar conexiones simples de TCP de Java y luego pude ejecutar el 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 vez de 114, era el mismo problema.

me he dado cuenta de que el problema era que yo había recopilado el nuevo programa C con opción "-lsocket" antes "-lsockx25", así que fue una pista. Entonces busqué en Google y me encontré con un problema similar:

link to java X25 Bug ID:4077576

Al final de este artículo, se menciona la opción LD_PRELOAD para forzar sockx25 biblioteca se carga por primera vez. Finalmente, la solución estaba en tiempo de ejecución:

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

bash$ java TestX25

y entonces todo está funcionando muy bien usar JNI.

referencia para LD_PRELOAD: link to java tuning

Cuestiones relacionadas