我正在尝试使用 JNI 编写我的第一个 Java/C 程序。这是“我的”代码的样子 - 它是从this http://stuf.ro/calling-c-code-from-java-using-jni网站:
/* 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 part:
/* 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.
#
我尝试过的:
Using -mno-cygwin
编译时标记,但由于我安装了最新版本的 Cygwin,因此不再支持它。
Using -mno-cygwin
标志与gcc-3
而不是 gcc - 但 Cygwin 无法识别gcc-3命令。
添加环境变量。这似乎是常见的解决方案,但不知何故它对我不起作用。在我的系统上,Cygwin 安装在D:\Programy\Cygwin
,因此我添加到的文件夹PATH
is D:\Programy\Cygwin\bin
,如图所示picture http://s4.postimg.org/pqqlhnuzh/image.png(抱歉,外部链接,我没有足够的声誉来发布图片)。
从我读过的所有答案来看,这个should有效,但事实并非如此。 Cygwin 不直接位于 C:\Cygwin 中是否存在问题?或者我做错了什么?我检查了文件夹,那里iscygwin1.dll,它没有丢失。
我在 64 位 Windows 8 上运行。 Cygwin版本:1.7.35-1,安装了整个Devel包。 GCC 版本是 4.9.2。
很抱歉这篇文章很长,我只是想提供尽可能多的信息。我已经被这个问题困扰好几天了,很高兴得到任何建议。
Edit:我刚刚注意到编译我的 C 文件gcc
上面的命令不会产生任何可执行文件,我觉得很奇怪。它也不会抛出任何错误或警告。对这个有什么想法吗?难道这就是我的麻烦的根源吗?
Edit 2:我刚刚发现这不应该是一个问题,我实际上是在制作一个库,而不是一个可执行文件。
Edit 3:好吧,我放弃了。这似乎是一个比我最初想象的要大得多的问题。无法做到这一点的原因是cygwin1.dll
无法动态加载,因为它在初始化时需要 4k 底部堆栈字节才能释放 - 如果从 JNI 调用它,这可能会出现问题。那里are一些克服它的方法;如果您正在寻找解决方案,这个帖子 http://lists-archives.com/cygwin/28776-creating-a-dll-in-cygwin-for-use-with-jni-without-mno-cygwin.html很好地总结了需要做什么this one http://elliotth.blogspot.cz/2005/08/porting-jni-code-to-win32-with-cygwin.html也可能有用。对于我的项目来说,这并不值得——但祝你好运。