world tutorial nazareno hello español ejemplos descargar java jni

java - tutorial - jni nazareno



¿Reescribe el código C en Java o usa JNI? (11)

Actualmente estoy desarrollando un proyecto escrito en Java. Tenemos un montón de algoritmos escritos en C / C ++ (al menos unos doscientos) que deben incorporarse en nuestro proyecto. Nuestras dos opciones son usar JNI para llamar a este código o para volver a escribir todos los algoritmos en Java.

Soy consciente de las consecuencias de usar JNI, puede abrir un nuevo conjunto de problemas, por lo que incluso se está considerando volver a escribir todo el código en Java. Pero la idea de reescribirlo parece ... equivocada. Los algoritmos han sido probados y, hasta donde sé, funcionan en el lenguaje equivocado.

En esta situación, ¿JNI facilitaría esta tarea? ¿O causaría más dolor de cabeza que reescribir el código en Java?

EDITAR # 1: Pregunta relacionada - Utilidad de JNI

EDITAR # 2: FYI - Nuestro proyecto Java no está diseñado para ser portátil de ninguna manera. Eso podría eliminar una de las desventajas de JNI, ya que supuestamente reduce la portabilidad.


Creo que encontrará que el uso de JNI no es tan desalentador como parece antes de sumergirse. Hay algunas concesiones y limitaciones importantes, pero en general JNI funciona bien y es bastante fácil de aprovechar según su intención.

Como otros han dicho, el mejor caso para JNI es:

  • Código nativo complejo (puntos de bonificación si ese código ya ha demostrado ser muy confiable)
  • Mínimo de ida y vuelta entre Java y el código nativo (desea minimizar los viajes a través de la capa JNI)
  • Interfaz de llamada razonablemente simple al código nativo (o también a Java si su código nativo necesita aprovechar los métodos / objetos de Java)

Definitivamente es posible automatizar o pseudo-automatizar la creación de una capa JNI para un conjunto razonablemente estructurado de componentes nativos. Eso valdría la pena si el número de componentes a envolver es grande.

La buena noticia con JNI es que debería ser sencillo para usted construir y probar esta interfaz, por ejemplo, debería poder escribir casos de prueba desde Java que exploten el comportamiento del algoritmo existente y, si hay problemas, lo más probable es que estén en el JNI. Capa en sí y no los algoritmos (dada su confianza en la implementación nativa).

Reescribir una gran cantidad de algoritmos C / C ++ en Java me parece mucho más riesgoso que usar JNI. Por supuesto, sin conocer los detalles es difícil de medir, pero existen diferencias sutiles entre las tecnologías que podría imaginar que impactan la implementación real de un algoritmo, por no mencionar el gran esfuerzo de ingeniería y el riesgo de error.

Una consideración final es la vida futura de estos algoritmos o componentes relacionados. ¿El conjunto de algoritmos es más o menos completo o continúa agregando? De cualquier manera, ¿existe un fuerte mantenimiento y / o razón de desarrollo futuro para favorecer una tecnología sobre la otra? Por ejemplo, si todo lo demás está en Java y todos los nuevos algoritmos estarán en Java y casi todos los integrantes del equipo están casi siempre codificando en Java, la reimplementación en Java comienza a parecer más atractiva a largo plazo.

Sin embargo, incluso con eso dicho, el trabajo triunfa consistente. Para una gran cantidad de componentes nativos que funcionan bien, todavía estaría dispuesto a comenzar con JNI incluso si fuera a hacer la transición a Java a largo plazo.


Creo que la respuesta está en la cantidad de acoplamiento que habría entre el código Java que llama y el código C / C ++ invocado y en el nivel de esfuerzo que implicaría la reescritura. Si su código C toma algunos números enteros, realiza algunos cálculos complejos y devuelve otro int. Utilice JNI. Si hay muchos complejos de ida y vuelta, pero los algoritmos son razonablemente simples, reescríbalos. La línea de falla es la conexión JNI. Si eso va a ser complejo, puede terminar escribiendo más código de interfaz JNI que el código de algoritmo para una reescritura.


Dale una oportunidad a JNI. Luego, si tiene algún problema, puede volver a escribir las problemáticas o envolver las llamadas JNI con servicios web y desplegarlas en diferentes cajas o cajas virtuales.


El puente entre C y Java es costoso, por lo que si tiene que pasar una gran cantidad de datos de un lado a otro, no se puede ganar llamando a C sobre JNI.

He visto a JNA como una alternativa razonable a JNI con mucho menos dolor para llamar a los métodos en una biblioteca compartida / DLL desde Java en una reflexión similar. Aun no lo he intentado.

Es posible que desee considerar la compilación de su código C como un binario de Linux MIPS que pueda interpretarse en Java. Razonablemente rápido, un poco difícil de configurar correctamente. Ver http://nestedvm.ibex.org/

También puede usar un backend llvm para gcc para compilar en bytecodes de bajo nivel que luego se pueden interpretar en Java. Este es también el enfoque adoptado con el iPhone SDK afaik en Mac OS X. http://llvm.org/


He estado en esta situación. Le sugiero que se acostumbre a usar las estructuras de datos de subprocesos múltiples que están disponibles en Java. En este punto, no querrá volver a las estructuras de datos de C ++.

También te darás cuenta de que puedes reescribir esos algoritmos mucho mejor usando técnicas más inteligentes, mejor polimorfismo, patrones de adaptadores, etc.

Cuando estás sentado en el código C / C ++, estás pensando que quieres aferrarte a él. Estás pensando en todo el amor que le pones. En unos pocos años, te darás cuenta de que al mantenerlo y usar JNI, has creado un monstruo. Cada vez que sufras un fallo del proceso, te arrepentirás de usar JNI. Después de solucionar el bloqueo del proceso, alguien querrá modificar un algoritmo en C ++ y querrá estrangularlo. Tendrán una excusa conveniente como "Todavía no estoy acostumbrado a Java".

Echa un vistazo a las estructuras de datos inmutables en Java. Ni siquiera piense en la velocidad que ejecutan estos viejos algoritmos C / C ++. Descubrí que mi nuevo código supera con creces a cualquiera de mi antiguo código C / C ++.

Escribir pruebas unitarias. Utilice NetBeans.

Saludos cordiales,

-Stosh


La respuesta simple es que si el código se va a llamar mucho Y el rendimiento es importante, entonces conviértalo a Java.

Las respuestas más complejas son:

  • Si la biblioteca se envuelve fácilmente en JNI, vaya con JNI
  • Si las pruebas que tiene para el código C / C ++ se convierten fácilmente a Java, entonces vaya al puerto

Yo haría lo siguiente:

  • toma uno de los algoritmos y envuélvelo en JNI
  • Toma el mismo algoritmo y conviértelo a Java.
  • Ver qué es más doloroso hacer
  • Si la velocidad es importante, perfile ambas versiones y vea cuál de ellas es aceptable.

Lea la publicación de Joel sobre " Pagar su deuda técnica " y luego conviértala ahora en lugar de pagar intereses en los próximos dos años y luego pague.

Quizás las bibliotecas reenvasadas podrían ser útiles en más lugares también. Si son útiles y lo suficientemente complejos para hacer que consideres mantenerlos en C, deben tener aún más uso una vez empaquetados en clases reutilizables, fácilmente distribuibles y comprensibles.


Si esto es solo para Windows, y ya están en una DLL, quizás JNA sería de utilidad. (Si el impacto de rendimiento para llamadas de función a través de JNA no es tan malo)


Si los "algoritmos" están bien empaquetados, ¿es posible crear un código de pegado automático a través de JNI? Eso reduciría el riesgo de errores (crear cientos de componentes individuales suena manualmente riesgoso) y haría que el costo sea independiente de la cantidad de algoritmos que se agreguen, más o menos.

La reescritura de cientos de componentes suena muy arriesgada, definitivamente recomendaría al menos investigar más de cerca JNI.

¿Qué requisitos de E / S tienen los algoritmos con respecto al resto del proyecto? Si están acoplados de forma bastante flexible, tal vez sería posible ejecutarlos como programas independientes independientes, invocados como subprocesos desde Java y utilizando, por ejemplo, stdio para compartir datos.


Si planea escribir proyectos futuros en Java, a diferencia de C / C ++. Mordería la bala ahora y transferiría el código a Java. Cuanto más espere, peor se volverá. El JNI suena atractivo en este caso, pero luego tendrá el problema de que alguien tenga que mantener el código C ++ cuando todos los demás estén en los nuevos y divertidos proyectos de Java.

Si este es un proyecto Java de una sola vez, ¿por qué lo escribes en Java?


Todavía consideraría seriamente la posibilidad de utilizar JNI, especialmente si puede minimizar el número de interfaces entre idiomas.

Si, por ejemplo, hay una pila completa de funciones en C que tienen todas las mismas entradas y salidas, pero que solo realizan un trabajo diferente en las entradas, envuélvalas en un solo contenedor JNI con un parámetro adicional para especificar qué algoritmo específico usar.