JNI JVM调用类路径 [英] JNI JVM Invocation Classpath

查看:89
本文介绍了JNI JVM调用类路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing a small C program using Cygwin that launches a Java Virtual Machine (libraries I am using require POSIX environment). So far, I have been able to get it to work as long as I place all of my classes in the same folder as the executable. However, I want to specify an actual JAR file that contains the application I want to run. This does not seem to work though, FindClass simply returns a null. I've narrowed it down to a problem with the classpath setting, like I said, because I can extract my jar file in the same directory as the executable and it will work. Here is a subset of my code:

我一直在随意遵循此指南: http://www.inonit.com/cygwin/jni/invocationApi/

I've loosely been following this guide: 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

Tried using -classpath and -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;
}

我如何错误地指定类路径?

How am I specifying the classpath incorrectly?

推荐答案

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

On x86-64, the Oracle Windows JDK headers define jint as long. This is 32 bits with Microsoft compilers (which the Oracle JDK is written for) but 64 bits with Cygwin gcc. Since JavaVMInitArgs contains some fields of this type, its binary layout is changed by this discrepancy.

我通过提供本地jni.h标头来解决此问题:

I worked around this by providing a local jni.h header:

#include "stdint.h"

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

#include_next "jni.h"

long重定义的范围内,我仅包含jni_md.h,因为它不包含任何其他标头,而jni.h包含几个标准标头,我们也不想受到影响

I'm including only jni_md.h within the scope of the long redefinition because it doesn't include any other headers, whereas jni.h includes a couple of standard headers which we would not want to be affected as well.

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

To ensure this is always included ahead of the Oracle header, use the -I compiler option to add its directory to the #include path.

这篇关于JNI JVM调用类路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆