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

时间:2015-04-07 08:25:02

标签: java c windows gcc cygwin

我正在尝试使用JNI制作我的第一个Java / C程序。以下是“我的”代码的外观 - 它是从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.
#

我尝试了什么:

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

  2. -mno-cygwin标记与gcc-3而不是gcc一起使用 - 但Cygwin无法识别 gcc-3 命令。

  3. 添加环境变量。这似乎是常见的解决方案,但不知何故它对我不起作用。在我的系统上,Cygwin安装在D:\Programy\Cygwin中,因此我添加到PATH的文件夹为D:\Programy\Cygwin\bin,如picture所示(对不起外部链接,我不知道)有足够的声誉来张贴图片。)

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

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

    很抱歉这篇长篇文章,我只想提供尽可能多的信息。我已经坚持了几天这个问题,并且很乐意接受任何建议。

    编辑:我刚才注意到如上所述使用gcc命令编译我的C文件并不会生成任何可执行文件,我觉得这很奇怪。它也不会抛出任何错误或警告。关于这个的任何想法?这可能是我麻烦的根源吗?

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

    编辑3:好的,我放弃了。这似乎比我最初想象的要大得多。无法做到这一点的原因是cygwin1.dll无法动态加载,因为它需要4k的底部堆栈字节在初始化时是免费的 - 如果从JNI调用它可能会有问题。 克服它的一些方法;如果您正在寻找解决方案,this post可以很好地总结需要完成的工作,this one也很有用。对于我的项目来说,这不值得 - 但祝你好运。

4 个答案:

答案 0 :(得分:4)

我发现无法做到这一点的原因是cygwin1.dll无法动态加载,因为它需要4k的底部堆栈字节才能在初始化时自由 - 如果它&那么可能会有问题#39;是从JNI打来的。

克服它的一些方法;如果您正在寻找解决方案, this post 可以很好地总结需要完成的工作,this one也很有用。我还找到了一个明确的解决方案here

答案 1 :(得分:2)

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

this site

中解释了一个更详细的例子

答案 2 :(得分:1)

由于我不能以低声誉发表评论,我会在那里说出来。

  1. cmd中echo %PATH%的结果是什么,您是否清楚地看到了Cygwin二进制文件的路径?
  2. java HelloWorldD:\Dokumenty\Fifth\src\hs_err_pid3156.log之后的日志内容是什么?
  3. 我会在你之后编辑这个答案。

答案 3 :(得分:-1)

我找到了解决这个问题的方法。运行配置脚本时,请使用

./configure --disable-static --enable-shared --host=x86_64-w64-mingw32

最后一个标志使用Cygwin附带的mingw编译器。 Mingw链接反对微软的msvcrt.dll而不是cygwin1.dll。