JNI_CreateJavaVM从Windows服务失败

时间:2014-11-16 08:29:02

标签: java windows service windows-services java-native-interface

当我从控制台运行我的代码时,它运行正常:创建了jvm并运行我的应用程序。但是,如果我将可执行文件作为Windows服务运行,则JNI_CreateJavaVM将失败并返回-1。 我是否需要在服务中配置某些内容才能使其正常工作?

由于

编辑:添加代码示例

我下载了Microsoft的服务示例,并根据我的需要对其进行了修改。基本上,当服务启动时,它会在一个新线程中运行此函数:

void CWSMService::ServiceWorkerThread(void)
{
    // Periodically check if the service is stopping.
    wchar_t szMessage[260];
    JNIEnv *env = NULL;
    JavaVM *vm = NULL; 
    while (!m_fStopping)
    {        
        jint res;
        jclass cls;
        jmethodID mid;

        res = JNI_CreateJavaVM(&vm, (void**)&env, getVMArgs());
        if(res < 0)
        {

            StringCchPrintf(szMessage, ARRAYSIZE(szMessage), L"Can't create Java VM (%d)", res);
            WriteEventLogEntry(szMessage, EVENTLOG_ERROR_TYPE); 
            break;
        }
        cls = env->FindClass(JAVA_BOOTSTRAP_CLASS);
        if (cls == NULL)
        {
            StringCchPrintf(szMessage, ARRAYSIZE(szMessage), L"Class not found %s", JAVA_BOOTSTRAP_CLASS_WIDE);
            WriteEventLogEntry(szMessage, EVENTLOG_ERROR_TYPE);                     
            vm->DestroyJavaVM();            
            break;
        }
        mid = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
        if (mid == 0)
        {
            StringCchPrintf(szMessage, ARRAYSIZE(szMessage), L"No main() method in class %s", JAVA_BOOTSTRAP_CLASS_WIDE);
            WriteEventLogEntry(szMessage, EVENTLOG_ERROR_TYPE); 
            vm->DestroyJavaVM();
            break;
        }
        env->CallStaticVoidMethod(cls, mid, getProgramArgs(env));        
        jthrowable exc = env->ExceptionOccurred();
        if (exc)
        {
            jboolean isCopy = false;
            jmethodID toString = env->GetMethodID(env->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;");
            jstring s = (jstring) env->CallObjectMethod(exc, toString);
            const char* utf = env->GetStringUTFChars(s, &isCopy);
            StringCchPrintf(szMessage, ARRAYSIZE(szMessage), L"Java Exception: %s", utf);
            WriteEventLogEntry(szMessage, EVENTLOG_ERROR_TYPE); 
            env->ReleaseStringUTFChars(s,utf);
            vm->DestroyJavaVM();
            break;
        }

    }

    if (vm) vm->DestroyJavaVM();    
    // Signal the stopped event.
    SetEvent(m_hStoppedEvent);
    Stop();
}


JavaVMInitArgs* CWSMService::getVMArgs()
{   
    JavaVMInitArgs* vm_args = new JavaVMInitArgs(); 
    JavaVMOption* options = new JavaVMOption[1];
    options[0].optionString = "-Djava.class.path=E:\\build_0670_19_00\\jar\\Itamar.jar";
    vm_args->version = JNI_VERSION_1_2;
    vm_args->options = options;
    vm_args->nOptions = 1;
    vm_args->ignoreUnrecognized = JNI_TRUE;
    return vm_args;
}

当我从Windows服务运行此可执行文件(由我的用户\本地服务运行)时,我在事件日志中收到此错误:

  

无法创建Java VM(-1)

但是当我从命令行运行它时它会成功并运行java代码。 我尝试使用32位java在32位模式下编译,在64位模式下使用64位java编译它,行为保持不变。

编辑2: 它在工作!! 对于未来可能会遇到类似问题的未来人员的一些注意事项: 1.当你查找一个课程(让我们说 com.mysite.foo.bar )你应该实际上这样称呼:     cls = env-&gt; FindClass(“com / mysite / foo / bar”); 2.在类路径中你可以使用双重'\',如: C:\\ com \\ mysite \\ foo \\ bar 或只是 / C:/ com / mysite / foo / bar

在我的情况下,它确实创建了JVM,但由于服务处于while循环中,因此第二次失败。它一开始并没有困扰我,因为我的java程序根本不应该返回,但在我的测试中我使用的程序只打印到屏幕......:/

0 个答案:

没有答案