2012-01-04 12 views
11

¿La interfaz nativa de Java (JNI) se ve afectada por problemas de compatibilidad con C++ ABI?¿La interfaz nativa de Java (JNI) se ve afectada por problemas de compatibilidad con C++ ABI?

Estoy desarrollando una aplicación Java. Me gustaría utilizar Java Native Interface (JNI) para llamar funciones en una biblioteca de C++. Tengo acceso al código de la biblioteca de C++, y puedo reconstruirlo, aunque lo necesite. (Por ejemplo, puedo vincular estáticamente el tiempo de ejecución de C++.)

Puedo exigir a mis usuarios que tengan JRE 6 o superior, pero no puedo exigirles que tengan un tiempo de ejecución de C++ en particular.

Un compañero de trabajo me señaló este artículo de blog: http://www.trilithium.com/johan/2005/06/static-libstdc/ que desaconseja el uso de código C++ cargado dinámicamente.

Otro compañero de trabajo me señaló este informe de error: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4694590 que detalla cómo se trataron estos problemas en Java 1.4.2.

La esencia del problema, según tengo entendido, es que la interfaz binaria de libstdC++ a menudo cambia. Si una aplicación C++ carga una biblioteca compartida de C++ que se creó con un compilador diferente, se cargarán dos bibliotecas incompatibles de libstdC++ en la memoria al mismo tiempo.

El informe de error explica la solución para Java 1.4.2: "Vinculamos estáticamente el tiempo de ejecución de C++ en JDK y habilitamos el script del enlazador para ocultar símbolos de libstdC++ y otros símbolos internos. Como resultado, esos símbolos se vuelven invisibles para el código JNI , y cuando algún código nativo necesita llamar al tiempo de ejecución de C++, la llamada se resolverá con el libstdC++ apropiado. Así que. Todavía hay dos libstdC++. Por lo que se cargan al mismo tiempo, pero debería ser benigno ".

Tengo algunas preguntas sobre esto.

En primer lugar, ¿OpenJDK continúa teniendo este enfoque?

[EDIT: Hice esta pregunta en la lista de distribución build-dev de OpenJDK. La respuesta es sí, HotSpot aún enlaza estáticamente libstdC++, pero aparentemente "la mayoría de las distribuciones de Linux lo arreglan". Otro desarrollador señala que esto ni siquiera requiere un parche: "Configuración STATIC_CXX = false debería ser suficiente (el valor predeterminado es true)."]

En segundo lugar, incluso en este caso, es que realmente benigna tener dos incompatibles libstdC++. ¿tan cargado al mismo tiempo?

En tercer lugar, este abordaje (para ocultar los símbolos en el JDK) trata todos los problemas de compatibilidad?

El artículo de blog mencionado anteriormente advierte que "el código compilado contra diferentes ABI simplemente no es compatible con archivos binarios". Y más tarde, "el soporte del tiempo de ejecución del lenguaje generalmente depende de que se compartan algunos datos, por ejemplo, para acceder a algún tipo de bloqueo o estructura de datos global (similar a cómo los programas C necesitan un error compartido)".

Esto hace que parezca que el problema no se puede resolver.

Por otra parte, tal vez la incompatibilidad ABI ya no es un problema. El artículo del blog tiene más de seis años. Una respuesta para otra pregunta de stackoverflow (GCC ABI compatibility) afirma que "Desde gcc-3.4.0, el ABI es compatible con versiones anteriores". ¿Ha sido eso exitoso?

Agradecería cualquier orientación sobre estos temas. (Y oye, ¡gracias por leer todo esto!)

ediciones

Mi pregunta estaba poniendo muy larga, por lo que no dio todos los detalles. Para abordar los comentarios de Will:

  1. Solo necesito llamar a las funciones externas "C". (Por ejemplo, uso javah para generar el archivo de encabezado C.)
  2. No necesito interactuar con el tiempo de ejecución de C++ en la JVM. (Básicamente solo necesito enviar cadenas a una biblioteca C++)

Respuesta

5

No lo sé. Pero eso nunca me detuvo.

Primero, depende de lo que quieras hacer. La premisa detrás de la vinculación estática del JDK es mejorar la portabilidad del propio JDK. Como no pueden esperar que los usuarios recompilen el JDK en su sistema operativo en particular, necesitaron un mecanismo para hacer portátil el binario final. Aparentemente la vinculación estática solucionó este problema.

A continuación, con respecto a JNI, primero llamará a las funciones C y no a C++, no creo que JNI tenga ningún tipo de enlace C++. Entonces, cualquier C++ que quieras usar tendrá que estar envuelto en una rutina C para hablar con Java.

A continuación, su C++ .so se vinculará dinámicamente con el sistema operativo más o menos como supongo. Parece bastante draconiano esperar que una rutina JNI no funcione con un enlace dinámico .so, y un C++. Por lo tanto, no debería ser diferente. Y, sin duda C++ es tan popular como lo es, parece igualmente draconiano que usted no sería capaz de vincular dinámicamente contra un C++ .so. Entonces, sean cuales sean los chanchullos que se necesiten para facilitar esto, es una suposición razonable que Ellos (tm) han hecho el trabajo para permitir que esto suceda.

Dicho esto, no debe haber ninguna expectativa de que cualquier C++ que esté utilizando tendrá alguna interacción con el tiempo de ejecución de C++ en el tiempo de ejecución de Java. Idealmente, simplemente coexistirán pacíficamente.

Dado que, suponiendo que esto funcione en absoluto, su C++ seguramente tendrá el problema de portabilidad ABI, ya que se vinculará dinámicamente y estará a merced del tiempo de ejecución de C++ instalado en el sistema operativo.

Así que, al final, me gustaría echarle un vistazo y ver qué pasa.

+1

JNI ciertamente tiene un enlace de C++. Pero sospecho que es una envoltura exclusiva del enlace C, por lo que debería ser inmune a los problemas de ABI. –

Cuestiones relacionadas