通过log4j发送JNI C stderr / stdout [英] Send JNI C stderr/stdout through log4j

查看:115
本文介绍了通过log4j发送JNI C stderr / stdout的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

My java app uses JNI to invoke a library written in C. This native library logs errors to stderr but I would like to redirect the error stream through my log4j logger somehow. Is this possible?

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

The C library is external - I don't have the source, so cannot change it.

谢谢

推荐答案

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

Note: I have not tried this answer; YMMV.

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

The POSIX method freopen will change the underlying file associated with a stream. As the manpage states: "The primary use of the freopen() function is to change the file associated with a standard text stream (stderr, stdin, or stdout)".

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

So, you could create your own JNI library that simply redirects the stream into a file. However, there are several serious roadblocks to making this work:


  1. 你需要确保你的Java
    程序本身不使用标准的
    流,因为它们也将被重定向

    的解决方法是在程序启动时将 System.out
    更改为其他内容。

  2. 第二方库的
    可能会绕过标准的
    文本流,并直接写入底层文件描述符
    。不太可能,但可能是
    。我不能
    记住freopen()只是
    更改缓冲流
    使用的文件描述符,或者实际
    重新打开底层fd。

  3. 您还需要

    更改连接到文件到记录器。

  1. You'll need to ensure that your Java program doesn't itself use standard streams, because they'll be redirected too. A workaround for this is to change System.out et al to something else when your program starts up.
  2. It's possible that the third-party library bypasses the standard text streams, and writes directly to the underlying file descriptor. It's unlikely but possible. I can't remember whether freopen() just changes the file descriptor used by the buffered stream, or actually re-opens the underlying fd.
  3. You'll still have the problem of connecting changes to the "file" to a logger.

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

That last point is by far the biggest: stdio writes to an OS-level file descriptor. You would have to create some Java-level code to read that descriptor and write to a log. My first thought is that you'd have to use a named pipe, and then spin up a new Java thread to read that pipe. But that won't be portable to different operating systems, and will that you manage the pipe name in your program's configuration.

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

Assuming that this is a server program, and does not itself process the standard IO streams, I think your best solution will be to configure Log4J with a console logger, and simply redirect all console output to a file.

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

Or talk to the people who wrote the library, to get them to add configurable logging.

这篇关于通过log4j发送JNI C stderr / stdout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆