2009-12-30 17 views
6

Mi aplicación Java utiliza JNI para invocar una biblioteca escrita en C. Esta biblioteca nativa registra errores en stderr pero me gustaría redirigir la secuencia de errores a través de mi log4j logger de alguna manera. es posible?Enviar JNI C stderr/stdout a log4j

La biblioteca C es externa. No tengo la fuente, por lo que no puedo cambiarla.

Gracias

+0

¿La capa JNI es parte de su aplicación o parte del conjunto de herramientas externo? – PSpeed

+0

Eso es parte del juego de herramientas externo también. – dogbane

+0

¿Con qué granularidad llama al código externo y cuántos datos pasan de un lado a otro? En otras palabras, ¿podrías engendrar el trabajo como un proceso infantil? Redirigir stdout o stderr del código C que no controlas es muy difícil. Pensé que lo había hecho antes, pero han pasado al menos 10 años desde que escribí ese tipo de código C y todo lo que puedo encontrar en línea se trata de redirigirlo a un archivo. – PSpeed

Respuesta

3

Nota: No he probado esta respuesta; YMMV.

El método POSIX freopen cambiará el archivo subyacente asociado a una secuencia. Como dice la página de manual: "El uso principal de la función freopen() es cambiar el archivo asociado con una secuencia de texto estándar (stderr, stdin o stdout)".

Por lo tanto, puede crear su propia biblioteca JNI que simplemente redirige la secuencia a un archivo. Sin embargo , existen varios obstáculos serios para hacer este trabajo:

  1. Usted necesita asegurarse de que el programa Java sí mismo no utilizar flujos estándares, porque van a ser redirigidos también. Una solución para es cambiar System.out y otros a otra cosa cuando se inicia el programa.
  2. Es posible que la biblioteca de terceros omita las secuencias de texto estándar y escriba directamente en el descriptor de archivo subyacente. Es poco probable pero posible. No puedo recordar si freopen() solo cambia el descriptor de archivo utilizado por la secuencia de almacenamiento intermedio, o realmente vuelve a abrir el fd subyacente.
  3. Todavía tendrá el problema de conectar cambios en el "archivo" a un registrador.

Este último punto es de lejos el más grande: stdio escribe en un descriptor de archivo de nivel de sistema operativo. Tendría que crear algún código de nivel Java para leer ese descriptor y escribir en un registro. Lo primero que pensé es que tendrías que usar un conducto con nombre y luego girar un nuevo hilo Java para leer ese conducto. Pero eso no será portátil para diferentes sistemas operativos, y administrará el nombre de la tubería en la configuración de su programa.

Suponiendo que se trata de un programa de servidor y no procesa los flujos de IO estándar, creo que la mejor solución será configurar Log4J con un registrador de consola y simplemente redirigir todos los resultados de la consola a un archivo.

O hable con las personas que escribieron la biblioteca para que agreguen el registro configurable.

-1

Mi C es un poco oxidado, pero puede que sea posible, ya que se puede invocar los métodos PrinStream desde dentro de una C a través de JNI. Pero tendrás que encontrar la manera de conectarte cuando se escriba la secuencia.

Actualización: Esto podría ayudar con enganchar en la salida estándar desde dentro de C:

http://www.gnu.org/software/hello/manual/libc/Hook-Functions.html

+0

Gracias, pero desafortunadamente no puedo cambiar la biblioteca C porque no es mía. – dogbane