JNI - проблема загрузки класса. Функция DefineClass не работает - PullRequest
0 голосов
/ 14 июля 2020

Я пытаюсь загрузить определенные c классы с помощью JNI. Проблема в том, что функция DefineClass (), похоже, не работает. И когда я пытаюсь запустить функцию FindClass (), она выдает ClassNotFoundError. Класс, который я пытаюсь загрузить, - это простой основной класс с основным методом и словом «привет из мира». И пакет правильный.

Вот что мне удалось сделать:

#include <iostream>
#include <fstream>
#include <jni.h>

int main() {

    JavaVM *jvm;
    JNIEnv* env;

    JavaVMInitArgs arguments;
    JavaVMOption* options = new JavaVMOption[1];
    
    options[0].optionString = "-Djava.class.path=";

    arguments.version = JNI_VERSION_1_8;
    arguments.nOptions = 1;
    arguments.options = options;
    arguments.ignoreUnrecognized = false;

    jint response = JNI_CreateJavaVM(&jvm, (void**)&env, &arguments);
    delete[] options;

    if (response != JNI_OK) {
        std::cin.get();
        return 0;
    }

    std::cout << "JVM load succeeded. Version ";
    jint ver = env->GetVersion();
    std::cout << ((ver >> 16) & 0x0f) << "." << (ver & 0x0f) << std::endl;

    std::ifstream fl("C:/Users/Admin/Desktop/Main.class");
    fl.seekg(0, std::ios::end);
    size_t lenght = fl.tellg();
    char* buffer = new char[lenght];
    fl.seekg(0, std::ios::beg);
    fl.read(buffer, lenght);
    fl.close();

    jclass mainClazz = env->DefineClass("Main", NULL, (const jbyte*) buffer, lenght);

    delete[] buffer;
    
    if (mainClazz == nullptr) {
        std::cout << "ERROR: class not found!";
        jvm->DestroyJavaVM();
        return 0;
    }

    jmethodID mainMethod = env->GetStaticMethodID(mainClazz, "main", "([Ljava/lang/String;)V");

    jobjectArray args = env->NewObjectArray(0, env->FindClass("java/lang/String"), 0);

    env->CallStaticVoidMethod(mainClazz, mainMethod, args);

    jvm->DestroyJavaVM();
    return 0;
}

Спасибо за совет.

1 Ответ

2 голосов
/ 15 июля 2020

Если DefineClass завершается ошибкой, вы должны увидеть, есть ли ожидающие исключения. Исключением, вероятно, будет то, что ваш файл класса каким-то образом искажен, потому что вы открываете свой ifstream в текстовом режиме, где он с радостью заменяет байты 0x0A парой 0x0D 0x0A.

Вместо этого используйте двоичный режим:

std::ifstream fl("C:/Users/Admin/Desktop/Main.class", std::ios::binary | std::ios::in);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...