Search code examples
javaclinkerjava-native-interfacelibraries

JNI_CreateJavaVM fails in 64bit C


I am having a similar issue to JNI_CreateJavaVM exit code -1?, except that my code runs when compiled in 32-bit, but fails when compiled in 64-bit. I am changing my JDK location for each configuration in Visual Studio Express 2010, using the Windows SDK 7.1 platform. My includes are:

C:\Program Files\Java\jdk1.6.0_29\include; (for jni.h)
C:\Program Files\Java\jdk1.6.0_29\include\win32; (for jni_md.h)

and my additional libraries are:

C:\Program Files\Java\jdk1.6.0_29\lib; (for jvm.lib and jawt.lib)

My source code is just simply trying to initialize the JVM in C and then looping infinitely to make sure that the command prompt stays open in VSC++.

#include "stdafx.h"
#include "jni.h"

JNIEnv* create_vm(JavaVM ** jvm);

int i;
JavaVM* jvm;
JNIEnv * env;

int _tmain(int argc, _TCHAR* argv[])
{
    printf("Hello World!");
    env = create_vm(&jvm);

    if (env == 0) { return 7; }

    i = 0;

    while (1) { i++; }

    return 0;
}

JNIEnv* create_vm(JavaVM ** jvm) {

    JavaVMInitArgs vm_args;
    int ret;
    JavaVMOption options;

    //Path to the java source code
    options.optionString = "-Djava.class.path=H:\\jarpath\\jarfile.jar";
    vm_args.version = JNI_VERSION_1_6; //JDK version. This indicates version 1.6
    vm_args.nOptions = 1;
    vm_args.options = &options;
    vm_args.ignoreUnrecognized = 0;

    ret = JNI_CreateJavaVM(jvm, (void**)&env, &vm_args);

    if(ret < 0)
        printf("\nUnable to Launch JVM\n");
    return env;
}

Again, this works with a 32-bit configuration, where the only difference is that the JDK root directory is a 32-bit folder (i.e. Program Files(x86)).

After printing,

Error occurred during initialization of VM
Unable to load native library: Can't find dependent libraries

The code exits with the following error in the VSC++ console window:

The program '[5684] JNI_Test.exe: Native' has exited with code 1 (0x1).

Is there anything I'm missing in terms of libraries or basic C coding? I haven't coded in C in a while and I'm not very familiar with the whole library linking in the first place.


Solution

  • Try this code (it does not use the export .lib files and it only needs the JNI headers and JVM.dll). I've used the command

    gcc -m64 -o test.exe small_test.cpp -I "C:\Program Files\Java\jdk1.6.0_25\include" -I "C:\Program Files\Java\jdk1.6.0_25\include\win32" -lstdc++
    

    to compile it (MinGW, but VC++ should work also. Mingw uses older MSVCRT)

    Check for GetLastError(). I suspect there's something wrong with the 64-bit C Run-Time.

    #include <windows.h>
    #include <stdio.h>
    #include <jni.h>
    #include <string.h>
    
    #define PATH_SEPARATOR ';' /* define it to be ':' on Solaris */
    #define USER_CLASSPATH "." /* where Prog.class is */
    
    typedef /*_JNI_IMPORT_OR_EXPORT_*/ jint (JNICALL *JNI_CreateJavaVM_func)(JavaVM **pvm, void **penv, void *args);
    
    JNI_CreateJavaVM_func JNI_CreateJavaVM_ptr;
    
    JNIEnv* create_vm(JavaVM ** jvm)
    {
        JNIEnv *env;
        JavaVMInitArgs vm_args;
        JavaVMOption options;
        HMODULE jvm_dll;
        int ret;
    
        options.optionString = "-Djava.class.path=D:\\monotest\\src_CJNIJava\\bin"; //Path to the java source code
        vm_args.version = JNI_VERSION_1_6; //JDK version. This indicates version 1.6
        vm_args.nOptions = 1;
        vm_args.options = &options;
        vm_args.ignoreUnrecognized = 0;
    
        jvm_dll = LoadLibrary("C:\\Program Files\\Java\\jre6\\bin\\server\\jvm.dll");
    
        /// You might check the GetLastError() here after the LoadLibrary()
        if(jvm_dll == NULL) { printf("can't load dll\n"); exit(1); }
    
        JNI_CreateJavaVM_ptr = (JNI_CreateJavaVM_func)GetProcAddress(jvm_dll, "JNI_CreateJavaVM");
    
        /// You might check the GetLastError() here
        if(JNI_CreateJavaVM_ptr == NULL) { printf("can't load function\n"); exit(1); }
    
        ret = JNI_CreateJavaVM_ptr(jvm, (void**)&env, &vm_args);
        if(ret < 0) { printf("\nUnable to Launch JVM\n"); }
        return env;
    }
    
    int main(int argc, char* argv[])
    {
        JNIEnv *env;
        JavaVM * jvm;
        env = create_vm(&jvm);
    
        if (env == NULL) { return 1; }
    
        int n = jvm->DestroyJavaVM();
        return 0;
    }