Search code examples
javacjava-native-interfacecygwinmalloc

JNI with native method malloc() causing crash on Cygwin


I have a custom DLL in C with one native function as simple as this:

void Java_main_Main_testMalloc(JNIEnv *env){
    char *c = malloc(sizeof(char)*5);
}

Inside Java:

package main;

public class Main {

    public static void main(String[] args){

        System.loadLibrary("libJNI_test1");
        Main m = new Main();
    }

    public Main(){
        testMalloc();
    }

    native void testMalloc();
}


Main:
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000018011ae47, pid=8604, tid=5464
#
# JRE version: Java(TM) SE Runtime Environment (8.0_05-b13) (build 1.8.0_05-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.5-b02 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C  [cygwin1.dll+0xdae47]

This is stripped version, of course. But i'm sure it crashes on malloc() due to all the tests i've made. Just comment out malloc, compile the DLL and it will be fine. Crashes with Fatal error: EXCEPTION_ACCESS_VIOLATION (0xc0000005). Sometimes it runs fine, other times it will hang at the point of where Java calls the native method... What i do wrong? How can i allocate native memory that i will temporary use as buffer or w/e?


Solution

  • The JNI declarations must have exactly the right parameters, including parameters that aren't used, and the function declaration must include the macros JNIEXPORT and JNICALL from jni.h. Without these, it's possible that the function won't return the stack to the correct state when it exits, resulting in undefined behaviour.

    Change the function declaration to say:

     JNIEXPORT void JNICALL Java_main_Main_testMalloc(JNIEnv *env, jobject obj){
         char *c = malloc(sizeof(char)*5);
     }
    

    and then see what you get.