代码之家  ›  专栏  ›  技术社区  ›  dogbane

通过log4j发送jni c stderr/stdout

  •  6
  • dogbane  · 技术社区  · 15 年前

    我的Java应用程序使用JNI调用在C中编写的库。这个本地库将错误记录到STDRR,但是我想通过我的Log4J记录器以某种方式重定向错误流。这有可能吗?

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

    谢谢

    2 回复  |  直到 14 年前
        1
  •  3
  •   kdgregory    15 年前

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

    posix方法 freopen 将更改与流关联的基础文件。如手册页所述:“freopen()函数的主要用途是更改与标准文本流(stderr、stdin或stdout)关联的文件。”

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

    1. 您需要确保您的Java 程序本身不使用标准 溪流,因为它们会 也已重定向。解决 这是要换的 System.out 等 当你的程序启动的时候。
    2. 有可能 第三方库忽略了标准 文本流,并直接写入 基础文件描述符。它是 不太可能,但可能。我不能 记住freopen()是否只是 更改使用的文件描述符 缓冲流,或者实际上 重新打开基础FD。
    3. 你会 仍然存在连接问题 将“文件”更改为记录器。

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

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

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

        2
  •  -1
  •   Kristopher Ives    15 年前

    我的C有点生疏,但可能有,因为您可以通过JNI从C中调用prinstream方法。但是当流被写入时,您必须找到一种方法来钩住它。

    更新:这可能有助于您从C:

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