6

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.

1
  • 5
    Don't worry about the lengthy posting - I think it is a great first question. Commented Apr 7, 2015 at 8:33

4 Answers 4

5

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.

Sign up to request clarification or add additional context in comments.

Comments

2

add header file which was generated using javah in your c file

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

and run using

java -Djava.library.path=. HelloWorld

if it does not work than try

java HelloWorld

a much more detailed example is explained in this site

3 Comments

Thank you for your reply. I added the header file as you correctly suggested and compiled the file again, but the problem (error with cygwin1.dll) still persists, no matter if I specify the java.library.path or not.
@Tilwaen okk than can you just follow the given site to get your desired result? if its possible?
I followed the instructions, even made new project with the exact same code they provided (I only added two libraries to C file which they omitted), compiled with Cygwin just as I did in my original post and got the exact same error. I also downloaded TCC which they use, but somehow can't get it to work - Cygwin has its terminal, but this compiler doesn't seem to have one and classic Windows cmd doesn't recognize tcc command, so I'm a bit confused about how to use it.
1

As i can't comment with my low reputation i'll say it there.

  1. What is the result of echo %PATH% in cmd, do you clearly see the path to Cygwin's binaries ?
  2. What are the contents of the logs after java HelloWorld in D:\Dokumenty\Fifth\src\hs_err_pid3156.log ?

I'll edit this answer after yours.

10 Comments

1. Yes, there is D:\Programy\Cygwin\bin; - pressed enter too soon, editing -
Oh well, comments may only be edited for 5 minutes... Sorry I can't edit the previous one. As to your questions: 1. Yes, there is D:\Programy\Cygwin\bin; among other paths. 2. Because the log is quite long, I put it on Pastebin. I already deleted the log to my original post, this one is related to the code on website that Bhargav Modi posted, which I tried later, but I think it relates to the same issue (cygwin1.dll).
To test if it works, open a cmd, go to your D:\Programy for example and try write ls. If it works, it shows that there is no problem with your path. If it doesn't recognize your ls, means it can't acces your /usr/bin as your program with cygwin1.dll
I succesfully went to D:\Programy. ls command worked flawlessly, it found every folder, including the Cygwin one.
I don't know sorry. Maybe try java -Djava.library.path="D:\Programy\Cygwin\bin" HelloWorld
|
-1

I figured out a solution to this problem. When running the configure script, use

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

The last flag uses the mingw compiler that comes packaged with Cygwin. Mingw links against Microsoft's msvcrt.dll rather that the cygwin1.dll.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.