通过log4j发送JNI C stderr/stdout

dog*_*ane 6 java java-native-interface logging

我的java应用程序使用JNI来调用用C编写的库.这个本机库将错误记录到stderr,但我想以某种方式通过我的log4j记录器重定向错误流.这可能吗?

C库是外部的 - 我没有源代码,因此无法更改它.

谢谢

kdg*_*ory 4

注意:我没有尝试过这个答案;YMMV。

POSIX 方法freopen将更改与流关联的底层文件。正如联机帮助页所述:“freopen() 函数的主要用途是更改与标准文本流(stderr、stdin 或 stdout)关联的文件”。

因此,您可以创建自己的 JNI 库,将流重定向到文件中。然而,实现这项工作存在几个严重的障碍:

  1. 您需要确保您的 Java 程序本身不使用标准流,因为它们也会被重定向。解决此问题的方法是System.out在程序启动时将 et al 更改为其他内容。
  2. 第三方库可能绕过标准文本流,直接写入底层文件描述符。这不太可能但有可能。我不记得 freopen() 是否只是更改缓冲流使用的文件描述符,或者实际上重新打开底层 fd。
  3. 您仍然会遇到将“文件”的更改连接到记录器的问题。

最后一点是迄今为止最重要的一点:stdio 写入操作系统级文件描述符。您必须创建一些 Java 级别的代码来读取该描述符并写入日志。我的第一个想法是,您必须使用命名管道,然后启动一个新的 Java 线程来读取该管道。但这不能移植到不同的操作系统,并且您将无法在程序配置中管理管道名称。

假设这是一个服务器程序,并且本身不处理标准 IO 流,我认为最好的解决方案是使用控制台记录器配置 Log4J,并将所有控制台输出重定向到文件。

或者与编写该库的人交谈,让他们添加可配置的日志记录。