Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot run C program from Java using Cygwin

I'm trying to make my first Java/C program using JNI. Here's how 'my' code looks - it's copied from this website:

/* 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");
}

Through Cygwin, I succesfully did

javac HelloWorld.java
javah HelloWorld

to create a header file like this:

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

So far so good. I can also compile the C program using:

$ 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

Now I should be able to do

java HelloWorld 

to see output from C, but instead I'm getting this error:

$ 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.
#

What I have tried:

  1. Using -mno-cygwin flag when compiling, but since I have the newest version of Cygwin installed, it's not supported anymore.

  2. Using -mno-cygwin flag with gcc-3 instead of gcc - but Cygwin doesn't recognize gcc-3 command.

  3. Adding an environment variable. This seems to be the common solution, but somehow it doesn't work for me. On my system, Cygwin is installed in D:\Programy\Cygwin, therefore the folder I added to PATH is D:\Programy\Cygwin\bin, as shown in the picture (sorry for external link, I don't have enough reputation to post pictures).

From all the answers I've read, this one should work, but it doesn't. Is there a problem with Cygwin not being directly in C:\Cygwin? Or am I doing something else wrong? I checked the folder and there is cygwin1.dll, it's not missing.

I'm running on Windows 8, 64-bit. Version of Cygwin: 1.7.35-1, installed the whole Devel package. GCC version is 4.9.2.

Sorry for the long post, I just wanted to provide as much information as I could. I've been stuck with this problem for several days now and will be glad for any advice.

Edit: I just noticed that compiling my C file with gcc command as above doesn't produce any executable file, which I find very strange. It also doesn't throw any error or warning. Any ideas on this one? Could that be the source of my trouble?

Edit 2: I just found out this should not be an issue, I'm actually making a library, not an executable file.

Edit 3: Okay, I'm giving up. It seems like much bigger issue than I initially thought it would be. The reason this cannot be done is that cygwin1.dll cannot be dynamically loaded, because it needs 4k of bottom stack bytes to be free when it's initializing - which might be a problem if it's being called from JNI. There are some ways to overcome it; if you're looking for a solution, this post sums up nicely what needs to be done and this one can also be useful. For my project, it's just not worth it - but good luck.

like image 742
Tilwaen Avatar asked Apr 07 '15 08:04

Tilwaen


1 Answers

I found that the reason this cannot be done is that cygwin1.dll cannot be dynamically loaded, because it needs 4k of bottom stack bytes to be free when it's initializing - which might be a problem if it's being called from JNI.

There are some ways to overcome it; if you're looking for a solution, this post sums up nicely what needs to be done and this one can also be useful. I also found an explicit solution here.

like image 173
Tilwaen Avatar answered Oct 04 '22 20:10

Tilwaen