¿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:
- Solo necesito llamar a las funciones externas "C". (Por ejemplo, uso javah para generar el archivo de encabezado C.)
- No necesito interactuar con el tiempo de ejecución de C++ en la JVM. (Básicamente solo necesito enviar cadenas a una biblioteca C++)
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. –