我正在尝试使用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. #
我曾经尝试过:
编译时使用-mno-cygwin
标志,但是由于我安装了最新版本的Cygwin,所以不再支持。
使用-mno-cygwin
标志与gcc-3
而不是gcc – 但Cygwin不能识别gcc-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调用,这可能是一个问题。
有一些方法可以克服它; 如果你正在寻找一个解决方案, 这个帖子很好地总结了需要做什么, 这也是有用的。 我也在这里找到了明确的解决方案
正如我不能评论我的低声誉,我会在那里说。
echo %PATH%
的结果是什么,你是否清楚地看到了Cygwin的二进制文件的路径? D:\Dokumenty\Fifth\src\hs_err_pid3156.log
java HelloWorld
之后的日志内容是什么? 我会在你之后编辑这个答案。