通过log4j发送JNI C stderr / stdout

时间:2009-12-30 22:44:06

标签: java logging java-native-interface

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

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

由于

2 个答案:

答案 0 :(得分:3)

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

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

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

  1. 您需要确保您的Java 程序本身不使用标准 溪流,因为他们会 重定向也是如此。解决方法 这是为了改变System.out等 程序启动时的其他内容。
  2. 有可能 第三方库绕过了标准 文本流,并直接写入 底层文件描述符。它的 不太可能但可能。我不能 记得freopen()是否只是 更改使用的文件描述符 缓冲流,或实际上 重新打开底层的fd。
  3. 您会 仍有连接问题 将“文件”更改为记录器。
  4. 最后一点是迄今为止最大的一点:stdio写入操作系统级文件描述符。您必须创建一些Java级代码来读取该描述符并写入日志。我的第一个想法是你必须使用命名管道,然后启动一个新的Java线程来读取该管道。但是,这将无法移植到不同的操作系统,并且您将在程序的配置中管理管道名称。

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

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

答案 1 :(得分:-1)

我的C有点生疏,但有可能,因为你可以通过JNI在C中调用PrinStream方法。但是你必须找到一种在流写入时挂钩的方法。

更新:这可能会帮助您从C:

中挂钩到stdout

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