无法使用 Cygwin 从 Java 运行 C 程序
Cannot run C program from Java using Cygwin
我正在尝试使用 JNI 制作我的第一个 Java/C 程序。这是 'my' 代码的样子 - 它是从 this 网站复制的:
/* HelloWorld.java */
public class HelloWorld {
native void helloFromC();
static {
System.loadLibrary("ctest");
}
static public void main(String argv[]) {
HelloWorld helloWorld = new HelloWorld();
helloWorld.helloFromC();
}
}
C 部分:
/* ctest.c */
#include <jni.h>
#include <stdio.h>
JNIEXPORT void JNICALL Java_HelloWorld_helloFromC
(JNIEnv * env, jobject jobj)
{
printf("Hello from C!\n");
}
通过Cygwin,我成功了
javac HelloWorld.java
javah HelloWorld
创建这样的头文件:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: helloFromC
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_helloFromC
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
到目前为止一切顺利。我还可以使用以下命令编译 C 程序:
$ gcc -D __int64="long long" -shared -I"D:\Programy\Java\JDK 8u31\include"
-I"D:\Programy\Java\JDK 8u31\include\win32" ctest.c -o ctest.dll
现在我应该可以做到了
java HelloWorld
查看 C 的输出,但我收到此错误:
$ java HelloWorld
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000018011ae47, pid=3156, tid=1176
#
# JRE version: Java(TM) SE Runtime Environment (8.0_31-b13) (build 1.8.0_31-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.31-b07 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C [cygwin1.dll+0xdae47]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# D:\Dokumenty\Fifth\src\hs_err_pid3156.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
我试过的:
编译时使用-mno-cygwin
标志,但由于我安装了最新版本的Cygwin,它不再被支持。
使用 -mno-cygwin
标志和 gcc-3
而不是 gcc - 但 Cygwin 不识别 gcc-3 命令。
正在添加环境变量。这似乎是常见的解决方案,但不知何故它对我不起作用。在我的系统上,Cygwin 安装在 D:\Programy\Cygwin
,因此我添加到 PATH
的文件夹是 D:\Programy\Cygwin\bin
,如 picture 所示(对不起外部 link , 我没有足够的声誉来 post 图片)。
从我读过的所有答案来看,这个 应该 有效,但它没有。 Cygwin 不是直接在 C:\Cygwin 中有问题吗?还是我做错了什么?我检查了文件夹,是cygwin1.dll,它没有丢失。
我 运行 使用 Windows 8,64 位。 Cygwin 版本:1.7.35-1,安装了整个 Devel 包。 GCC 版本是 4.9.2.
抱歉这么长post,我只是想提供尽可能多的信息。我已经被这个问题困扰好几天了,很高兴收到任何建议。
编辑: 我刚刚注意到用 gcc
命令编译我的 C 文件并没有生成任何可执行文件,我觉得这很奇怪。它也不会抛出任何错误或警告。对此有什么想法吗?这会是我麻烦的根源吗?
编辑 2: 我刚刚发现这应该不是问题,我实际上是在制作库,而不是可执行文件。
编辑 3: 好吧,我放弃了。这似乎比我最初想象的要大得多。无法做到这一点的原因是 cygwin1.dll
无法动态加载,因为它在初始化时需要 4k 的底部堆栈字节是空闲的——如果它是从 JNI 调用的,这可能是个问题。 有一些方法可以克服它;如果您正在寻找解决方案,this post sums up nicely what needs to be done and this one 也很有用。对于我的项目,这不值得 - 但祝你好运。
在您的 c 文件中添加使用 javah
生成的头文件
/* ctest.c */
#include "HelloWorld.h"
#include <jni.h>
#include <stdio.h>
JNIEXPORT void JNICALL Java_HelloWorld_helloFromC
(JNIEnv * env, jobject jobj)
{
printf("Hello from C!\n");
}
和 运行 使用
java -Djava.library.path=. HelloWorld
如果不行就试试
java HelloWorld
中解释了一个更详细的示例
由于我的声誉低无法发表评论,所以我会在那里说出来。
- cmd中
echo %PATH%
的结果是什么,你看清楚Cygwin的二进制文件的路径了吗?
D:\Dokumenty\Fifth\src\hs_err_pid3156.log
java HelloWorld
之后的日志内容是什么?
我会在你的之后编辑这个答案。
我发现无法做到这一点的原因是 cygwin1.dll
无法动态加载,因为它在初始化时需要 4k 底部堆栈字节空闲 - 如果它被调用,这可能是个问题来自 JNI。
有一些方法可以克服它;如果您正在寻找解决方案,this post sums up nicely what needs to be done and this one can also be useful. I also found an explicit solution here.
我找到了解决这个问题的方法。 运行配置脚本时,使用
./configure --disable-static --enable-shared --host=x86_64-w64-mingw32
最后一个flag使用了Cygwin自带的mingw编译器。 Mingw 链接针对的是 Microsoft 的 msvcrt.dll 而不是 cygwin1.dll。
我正在尝试使用 JNI 制作我的第一个 Java/C 程序。这是 'my' 代码的样子 - 它是从 this 网站复制的:
/* HelloWorld.java */
public class HelloWorld {
native void helloFromC();
static {
System.loadLibrary("ctest");
}
static public void main(String argv[]) {
HelloWorld helloWorld = new HelloWorld();
helloWorld.helloFromC();
}
}
C 部分:
/* ctest.c */
#include <jni.h>
#include <stdio.h>
JNIEXPORT void JNICALL Java_HelloWorld_helloFromC
(JNIEnv * env, jobject jobj)
{
printf("Hello from C!\n");
}
通过Cygwin,我成功了
javac HelloWorld.java
javah HelloWorld
创建这样的头文件:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: helloFromC
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_helloFromC
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
到目前为止一切顺利。我还可以使用以下命令编译 C 程序:
$ gcc -D __int64="long long" -shared -I"D:\Programy\Java\JDK 8u31\include"
-I"D:\Programy\Java\JDK 8u31\include\win32" ctest.c -o ctest.dll
现在我应该可以做到了
java HelloWorld
查看 C 的输出,但我收到此错误:
$ java HelloWorld
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000018011ae47, pid=3156, tid=1176
#
# JRE version: Java(TM) SE Runtime Environment (8.0_31-b13) (build 1.8.0_31-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.31-b07 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C [cygwin1.dll+0xdae47]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# D:\Dokumenty\Fifth\src\hs_err_pid3156.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
我试过的:
编译时使用
-mno-cygwin
标志,但由于我安装了最新版本的Cygwin,它不再被支持。使用
-mno-cygwin
标志和gcc-3
而不是 gcc - 但 Cygwin 不识别 gcc-3 命令。正在添加环境变量。这似乎是常见的解决方案,但不知何故它对我不起作用。在我的系统上,Cygwin 安装在
D:\Programy\Cygwin
,因此我添加到PATH
的文件夹是D:\Programy\Cygwin\bin
,如 picture 所示(对不起外部 link , 我没有足够的声誉来 post 图片)。
从我读过的所有答案来看,这个 应该 有效,但它没有。 Cygwin 不是直接在 C:\Cygwin 中有问题吗?还是我做错了什么?我检查了文件夹,是cygwin1.dll,它没有丢失。
我 运行 使用 Windows 8,64 位。 Cygwin 版本:1.7.35-1,安装了整个 Devel 包。 GCC 版本是 4.9.2.
抱歉这么长post,我只是想提供尽可能多的信息。我已经被这个问题困扰好几天了,很高兴收到任何建议。
编辑: 我刚刚注意到用 gcc
命令编译我的 C 文件并没有生成任何可执行文件,我觉得这很奇怪。它也不会抛出任何错误或警告。对此有什么想法吗?这会是我麻烦的根源吗?
编辑 2: 我刚刚发现这应该不是问题,我实际上是在制作库,而不是可执行文件。
编辑 3: 好吧,我放弃了。这似乎比我最初想象的要大得多。无法做到这一点的原因是 cygwin1.dll
无法动态加载,因为它在初始化时需要 4k 的底部堆栈字节是空闲的——如果它是从 JNI 调用的,这可能是个问题。 有一些方法可以克服它;如果您正在寻找解决方案,this post sums up nicely what needs to be done and this one 也很有用。对于我的项目,这不值得 - 但祝你好运。
在您的 c 文件中添加使用 javah
生成的头文件
/* ctest.c */
#include "HelloWorld.h"
#include <jni.h>
#include <stdio.h>
JNIEXPORT void JNICALL Java_HelloWorld_helloFromC
(JNIEnv * env, jobject jobj)
{
printf("Hello from C!\n");
}
和 运行 使用
java -Djava.library.path=. HelloWorld
如果不行就试试
java HelloWorld
中解释了一个更详细的示例
由于我的声誉低无法发表评论,所以我会在那里说出来。
- cmd中
echo %PATH%
的结果是什么,你看清楚Cygwin的二进制文件的路径了吗? D:\Dokumenty\Fifth\src\hs_err_pid3156.log
java HelloWorld
之后的日志内容是什么?
我会在你的之后编辑这个答案。
我发现无法做到这一点的原因是 cygwin1.dll
无法动态加载,因为它在初始化时需要 4k 底部堆栈字节空闲 - 如果它被调用,这可能是个问题来自 JNI。
有一些方法可以克服它;如果您正在寻找解决方案,this post sums up nicely what needs to be done and this one can also be useful. I also found an explicit solution here.
我找到了解决这个问题的方法。 运行配置脚本时,使用
./configure --disable-static --enable-shared --host=x86_64-w64-mingw32
最后一个flag使用了Cygwin自带的mingw编译器。 Mingw 链接针对的是 Microsoft 的 msvcrt.dll 而不是 cygwin1.dll。