我正在使用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;
}
如何错误地指定类路径?
答案 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
路径。