从Java JNI捕获C的stderr

6
我有一个用C语言开发的大型程序,大部分功能都有几个fprintf(stderr, "message")语句。
但现在我需要在Java程序中使用这些函数。所以,我实现了一个JNI接口来实现Java和C之间的通信。一切都很好,Java和C可以通信,但现在我想要在Java中捕获C的多个stderr...怎么做?
干杯 ;)

+1 和星号...但我担心答案将是让 C 代码抛出消息,然后捕获/打印(对于 C 可执行文件),以及捕获/抛出 JNI 封装。 - Tim Bender
你能在Java控制台中看到fprintf的输出吗? - Denis Tulskiy
4个回答

1

根据我自己的经验,我可以说JNI桥对通过标准流输出的内容的重要性有非常奇怪的看法。通常情况下,它会进行大量缓存、不可预测的分块和定时抛出,并且我们没有找到如何强制刷新的方法。

最终我们采用了在C端一起完成的日志记录,通过大规模的正则表达式替换*printf()语句,将其转化为文件日志。尾随生成的日志文件比任何试图说服JVM在缓冲区中确实需要日志记录的尝试更加可靠,因为这是由C层决定的,而不是由JVM决定的。


0

对此的一种可能解决方法是执行以下操作,参考 http://www.thecodingforums.com/threads/redirect-cout-and-cerr-to-system-out-and-system-err.635861/

我想出的解决方案是创建一些JNI代码,其中包含两个方法:

  • 一个将标准输出重定向到管道中的方法
  • 一个在那里获取存储的输出的方法

然后,流程如下:

  • 调用重定向函数
  • 进行多个其他JNI调用
  • 获取输出并将其写入想要的位置

上述链接提供的实现看起来像这样

#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <jni.h>

#include "Nat1.h"

#define MAXBUF 20480

static int oldstdout;
static int pipehandles[2];
static char buf[MAXBUF];

JNIEXPORT void JNICALL Java_Nat2_init(JNIEnv *cntx, jobject me)
{
    oldstdout = _dup(_fileno(stdout));
    _pipe(pipehandles,MAXBUF,_O_BINARY);
    _dup2(pipehandles[1],_fileno(stdout));
 }

JNIEXPORT jstring JNICALL Java_Nat2_done(JNIEnv *cntx, jobject me)
{
    int n;
    fflush(stdout);
    _dup2(oldstdout,_fileno(stdout));
    n = _read(pipehandles[0],buf,sizeof(buf));
    buf[n] = '\0';
    return (*cntx)->NewStringUTF(cntx,buf);
}

这有点繁琐,因为您需要开始捕获stderr,然后在以后想要查看它时获取它。


0
当你调用JNI库时,你会将它加载到JVM进程中,因此库的STDOUT和STDERR将是JVM的STDOUT和STDERR。所以问题是特定于操作系统的,更像是“如何使进程读取自己的STDOUT / STDERR?”
有几种可能性可以内部捕获/重定向stdout?,但我不认为很容易仅读取您库的STDOUT或STDERR(我认为在执行重定向后,您无法返回使用控制台进行输出 (*))。
正如评论所述,答案将严重依赖于你的操作系统。
(*)我可能错了,我不太精通C /系统编程。

0

根据这个答案,我认为你应该能够重新分配进程的stderr。在JNI函数执行时,您需要另一个线程从中读取,以避免阻塞。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接