Запуск JVM через JNI_CreateJavaVM в OSX только для консоли - PullRequest
1 голос
/ 26 марта 2020

Я пытаюсь запустить JVM из моей программы C / Obj C, но у меня есть некоторые проблемы с отображением визуальных элементов, таких как, например, окно, в Catalina.

Часть программы, которая использует невизуальные элементы, т.е. консоль & System.out работает нормально. Но не отображается какое-либо окно приложения, хотя появляется соответствующий значок Dock, который при нажатии ничего не делает.

Я написал вспомогательную функцию для запуска JVM. В качестве аргументов он имеет

  • расположение libjvm.dylib
  • параметров JVM
  • размер параметров jvm
  • основных аргументов
  • размер основных аргументов
  • основной класс

Мне кажется, что я что-то упускаю, но не могу понять, что. Есть идеи?

Вот код:

typedef jint (*JNI_CreateJavaVM_f)(JavaVM **, void **, void *);

int launchjvm(char *jvmlib, char **jvmopts, int c_jvmopts, char **args, int c_args, char *mainclass)
{
    JavaVM *vm;
    JNIEnv *env;
    JavaVMInitArgs vm_args;
    JavaVMOption options[c_jvmopts];

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    memset(&vm_args, 0, sizeof(vm_args));
    vm_args.version = JNI_VERSION_1_8;
    vm_args.ignoreUnrecognized = JNI_TRUE;

    for (int i = 0; i < c_jvmopts; i++)
        options[i].optionString = jvmopts[i];
    vm_args.options = options;
    vm_args.nOptions = c_jvmopts;

    void *lib_handle = dlopen(jvmlib, RTLD_LOCAL | RTLD_LAZY);
    if (!lib_handle)
    {
        printf("[%s] Unable to load library: %s\n", __FILE__, dlerror());
        return 1;
    }
    JNI_CreateJavaVM_f JNI_CreateJavaVM = dlsym(lib_handle, "JNI_CreateJavaVM");
    if (!JNI_CreateJavaVM)
    {
        printf("[%s] Unable to get symbol: %s\n", __FILE__, dlerror());
        return 1;
    }

    jint res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args);
    if (res != JNI_OK)
    {
        printf("Failed to create Java VM\n");
        return res;
    }

    jclass cls = (*env)->FindClass(env, mainclass);
    if (cls == NULL)
    {
        printf("Failed to find %s class\n", mainclass);
        return 1;
    }

    jmethodID mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
    if (mid == NULL)
    {
        printf("Failed to find main function in class %s\n", mainclass);
        return 2;
    }

    jobjectArray main_args = (*env)->NewObjectArray(env, c_args, (*env)->FindClass(env, "java/lang/String"), NULL);
    for(int i = 0 ; i < c_args ; i++)
        (*env)->SetObjectArrayElement(env, main_args, i, (*env)->NewStringUTF(env, args[i]));

    int result = 0;
    (*env)->CallStaticVoidMethod(env, cls, mid, main_args);
    if ((*env)->ExceptionOccurred(env)) { // check if an exception occurred
        (*env)->ExceptionDescribe(env); // print the stack trace
        result = -1;
    }

    (*vm)->DestroyJavaVM(vm);
    [pool drain];
    return result;
}
...