调用JNI_CreateJavaVM后cout无法正常输出是什么原因?
问题根因
这个现象是Windows平台Oracle JDK 8及更早版本的已知行为:JNI_CreateJavaVM初始化JVM的时候,会默认修改C/C++标准输出/标准错误的文件描述符映射,把它们重定向到JVM内部的输出缓冲,或者直接解绑原有stdout和控制台的绑定,导致后续的cout/printf输出的内容不会写到控制台窗口。
可行解决方案
- 方案1:在调用
JNI_CreateJavaVM前强制绑定stdout到当前控制台
在初始化JVM的代码前加入以下代码即可:#include <stdio.h> // 关闭stdout缓冲,所有内容立即输出 setvbuf(stdout, NULL, _IONBF, 0); // 强制stdout、stderr绑定到当前控制台输出 freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stderr); - 方案2:给JVM添加启动参数关闭输出重定向
新增一条JVM启动参数禁用JVM修改stdout映射,修改你的参数配置代码如下:JavaVMOption* options = new JavaVMOption[2]; options[0].optionString = (char*) "-Djava.class.path=."; options[1].optionString = (char*) "-Dsun.stdout.encoding=UTF-8"; // 新增这行 vm_args.nOptions = 2; - 方案3:如果不需要获取JVM启动阶段的输出,也可以在
JNI_CreateJavaVM调用完成后,再执行方案1中的freopen代码,同样可以恢复cout的控制台输出。
额外注意
你当前的编译命令里路径包含空格,建议给路径加引号避免偶现的编译错误:
g++ main.cpp -o main.exe -I"C:\Program Files\Java\jdk1.8.0_311\include" -I"C:\Program Files\Java\jdk1.8.0_311\include\win32" -L"C:\Program Files\Java\jdk1.8.0_311\lib" -ljvm
运行前请保证C:\Program Files\Java\jdk1.8.0_311\jre\bin\server目录已加入系统PATH环境变量,否则会出现运行时找不到jvm.dll的报错。
内容的提问来源于stack exchange,提问作者hackedXD
相关产品推荐
相关产品推荐

