无法使用Cygwin从Java运行C程序

我正在尝试使用JNI创build我的第一个Java / C程序。 以下是“我的”代码的外观 – 从以下网站复制而来:

/* 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 

像这样创build一个头文件:

 /* 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. # 

我曾经尝试过:

  1. 编译时使用-mno-cygwin标志,但是由于我安装了最新版本的Cygwin,所以不再支持。

  2. 使用-mno-cygwin标志与gcc-3而不是gcc – 但Cygwin不能识别gcc-3命令。

  3. 添加一个环境variables。 这似乎是常见的解决scheme,但不知何故,它不适合我。 在我的系统中,Cygwin安装在D:\Programy\Cygwin ,因此我添加到PATH的文件夹是D:\Programy\Cygwin\bin ,如图所示(对于外部链接抱歉,我没有足够的信誉张贴图片)。

从我读过的所有答案中,这一个应该工作,但事实并非如此。 Cygwin没有直接在C:\ Cygwin中出现问题吗? 还是我在做别的事呢? 我检查了文件夹,并有cygwin1.dll,它不会丢失。

我在Windows 8,64位上运行。 Cygwin的版本:1.7.35-1,安装了整个Devel包。 GCC版本是4.9.2。

对不起,我只是想提供尽可能多的信息。 我一直坚持这个问题好几天了,并会很高兴的任何build议。

编辑:我只是注意到编译我的C文件与上面的gcc命令不会产生任何可执行文件,我觉得很奇怪。 它也不会抛出任何错误或警告。 任何想法在这一个? 这可能是我的麻烦来源吗?

编辑2:我只是发现这不应该是一个问题,我实际上是一个库,而不是一个可执行文件。

编辑3:好吧,我放弃。 这似乎是比我最初想象的要大得多的问题。 之所以不能这样做,是因为cygwin1.dll不能被dynamic加载,因为在初始化时需要4k的底层堆栈字节空闲 – 如果是从JNI调用,这可能是一个问题。 有一些方法可以克服它; 如果你正在寻找一个解决scheme, 这个post很好地总结了需要做什么, 这也是有用的。 对于我的项目来说,这是不值得的 – 但是祝你好运。

添加在你的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 

在这个网站上解释了一个更详细的例子

我发现这个不能做的原因是cygwin1.dll不能被动态加载,因为它需要4k的底层堆栈字节在初始化时是自由的 – 如果是从JNI调用,这可能是一个问题。

有一些方法可以克服它; 如果你正在寻找一个解决方案, 这个帖子很好地总结了需要做什么, 这也是有用的。 我也在这里找到了明确的解决方案

正如我不能评论我的低声誉,我会在那里说。

  1. cmd中echo %PATH%的结果是什么,你是否清楚地看到了Cygwin的二进制文件的路径?
  2. D:\Dokumenty\Fifth\src\hs_err_pid3156.log java HelloWorld之后的日志内容是什么?

我会在你之后编辑这个答案。