JNI JVM调用类路径

时间:2014-07-21 16:00:52

标签: java c java-native-interface cygwin

我正在使用Cygwin编写一个小型C程序,它启动了一个Java虚拟机(我正在使用的库需要POSIX环境)。到目前为止,只要我将所有类放在与可执行文件相同的文件夹中,我就能够使它工作。但是,我想指定一个包含我想要运行的应用程序的实际JAR文件。这似乎不起作用,FindClass只返回一个null。我已经将它缩小到类路径设置的问题,就像我说的那样,因为我可以将jar文件解压缩到与可执行文件相同的目录中,并且它将起作用。这是我的代码的一个子集:

我已经松散地遵循了本指南:http://www.inonit.com/cygwin/jni/invocationApi/

int main( int argc, char *argv[] )
{
        void* jvmDllHandle;
        JNIEnv* jenv;
        JavaVM* jvm;
        JavaVMInitArgs args;
        JavaVMOption options[1];
        jclass cls;
        jmethodID mainMethod;
        jobjectArray appArgs;
        jstring arg0;

        assert( cygwin_internal( CW_SYNC_WINENV ) != 1UL );

        jvmDllHandle = LoadLibrary( "c:\\Path\\To\\Application\\jre\\bin\\server\\jvm.dll" );
        createJavaVM = dlsym( jvmDllHandle, "JNI_CreateJavaVM" );

        args.version = JNI_VERSION_1_6;
        args.nOptions = 1;
        options[0].optionString = "-Djava.class.path=c:\\Path\\To\\Application\\TheJarFile.jar";
        args.options = options;
        args.ignoreUnrecognized = JNI_FALSE;

        createJavaVM( &jvm, (void **) &jenv, &args );

        cls = (*jenv)->FindClass( jenv, "some/package/MainClass" );
        assert( cls != NULL );  // This fails.

        /// Omitted...

        return 0;
}

尝试使用-classpath和-cp

int main( int argc, char *argv[] )
{
        void* jvmDllHandle;
        JNIEnv* jenv;
        JavaVM* jvm;
        JavaVMInitArgs args;
        JavaVMOption options[1];
        jclass cls;
        jmethodID mainMethod;
        jobjectArray appArgs;
        jstring arg0;

        assert( cygwin_internal( CW_SYNC_WINENV ) != 1UL );

        jvmDllHandle = LoadLibrary( "c:\\Path\\To\\Application\\jre\\bin\\server\\jvm.dll" );
        createJavaVM = dlsym( jvmDllHandle, "JNI_CreateJavaVM" );

        args.version = JNI_VERSION_1_6;
        args.nOptions = 1;
        options[0].optionString = "-classpath c:\\Path\\To\\Application\\TheJarFile.jar";
        args.options = options;
        args.ignoreUnrecognized = JNI_FALSE;

        createJavaVM( &jvm, (void **) &jenv, &args );

        cls = (*jenv)->FindClass( jenv, "some/package/MainClass" );
        assert( cls != NULL );  // This fails.

        /// Omitted...

        return 0;
}

如何错误地指定类路径?

1 个答案:

答案 0 :(得分:3)

在x86-64上,Oracle Windows JDK标头将jint定义为long。这是32位与Microsoft编译器(用于编写Oracle JDK)但64位与Cygwin gcc。由于JavaVMInitArgs包含此类型的某些字段,因此这种差异会改变其二进制布局。

我通过提供本地jni.h标题解决了这个问题:

#include "stdint.h"

#define __int64 int64_t
#define long int32_t
#include "jni_md.h"
#undef long

#include_next "jni.h"

我只在jni_md.h重新定义的范围内包含long,因为它不包含任何其他标头,而jni.h包含一些我们不会包含的标准标头我也希望受到影响。

要确保始终包含在Oracle标头之前,请使用-I编译器选项将其目录添加到#include路径。