JNI控制台输出的顺序

在Java中使用调用c++程序时,遇到了标准输出输出顺序的一个问题。

假设有Java代码如下

public class Main {

    public static void main(String[] args) {
        System.out.println("Hello World!");
        System.loadLibrary("JNITest");
        HelloCpp a = new HelloCpp();
        a.hellocpp();
    }
}

public class HelloCpp {
    public native void hellocpp();
}

C++代码如下

JNIEXPORT void JNICALL Java_HelloCpp_hellocpp(JNIEnv *, jobject)
{
	printf("hello from cpp\n");
}

上述代码成功编译执行后的控制台输出为

Hello World!

Hello Java!

hello from cpp

这样的内容,显然不是我们所预期的。具体来说就是即使C++的输出在执行的时候在Java之前,Java的也会先输出,C++的会后输出。百度之后找到了这样一个帖子

https://bbs.csdn.net/topics/391939316

有人回答是

如我们上面谈到的,这里涉及到跨进程通信,这个过程是耗时的,所以可能存在消息延迟。

就结论而言,该说法是错的。在得到结论之前我们来更换一下代码试试。C++的改成如下代码:

JNIEXPORT void JNICALL Java_HelloCpp_hellocpp(JNIEnv *, jobject)
{
	cout << "hello from cpp" << endl;
}

我们会得到输出

Hello World!

hello from cpp

Hello Java!

看吧,如果如帖子中的回答那样,这里不应该出现这样的结果的。几乎所有C++的书上都会写std::endl和"\n"的区别,那就是刷新缓冲区。因此使用如下代码是可以得到同样的结果的

JNIEXPORT void JNICALL Java_HelloCpp_hellocpp(JNIEnv *, jobject)
{
	printf("hello from cpp\n");
	cout.flush();
}
这就说明了,JNI的C++程序的标准输出拥有自己独立的缓冲区,Java代码拥有自己的缓冲区,它们互不影响,每次刷新缓冲区,C++才能将标准输出送到Java的控制台,二者输出顺序与进程通信什么的没有丝毫关系,仅仅是因为缓冲区的问题。

猜你喜欢

转载自blog.csdn.net/hnlylyb/article/details/80708880
今日推荐