Загрузка измененных файлов классов в JVM с использованием JNI

Я разрабатываю Java IDE для Windows в качестве учебного проекта и столкнулся с барьером, который не могу обойти.

Я использую JNI для вызова JVM и использую javac для компиляции своего кода.

JVM запускается правильно, и когда java-код компилируется в первый раз, JVM берет их из путей к классам и правильно запускает.

Но после того, как я редактирую java-файл, компилирую (использую скрипт для компиляции) и запускаю код, JVM по-прежнему загружает файл класса, который был скомпилирован во время первого запуска. Я должен остановить весь процесс и снова запустить JVM, чтобы изменения вступили в силу.

Я знаю, что должен быть способ, которым это обрабатывается в IDE, таких как Eclipse или IntelliJ. Но я не мог найти, как это сделать. Я был бы очень признателен, если кто-то может мне помочь.

Код, который я использовал для поиска и загрузки файлов классов, приведен ниже.

bool load(const char* classFile)
{   
    JNIEnv* env;
    bool isAttached = Interpreter::getEnv(&env);
    auto javacls = env->FindClass(classFile);
    if (javacls == nullptr)
    {
        getLogger().error("ERR: Loading class file %s failed", classFile);
        env->ExceptionDescribe();
        return false;
    }
    auto classInstance = getObject(javacls);

    if (classInstance == nullptr)
    {
        getLogger().error("ERR: Invalid Object");
        return false;
    }

    return true;
}

person Will_Panda    schedule 21.11.2017    source источник
comment
Изменение кода «на лету» работает только через Instrumentation API, в случае собственного кода — JVMTI; это то, что используют отладчики.   -  person Holger    schedule 21.11.2017
comment
@Холгер Спасибо. Я посмотрю на апи.   -  person Will_Panda    schedule 21.11.2017


Ответы (2)


Вы должны запускать тестируемый код под отдельным ClassLoader и использовать новый после каждой компиляции, возможно, даже для каждого запуска.

Вам не нужен никакой JNI.

person user207421    schedule 21.11.2017
comment
Да, я знаю, что могу написать это исключительно на Java. Но мне нужно сделать это с помощью JNI, поскольку я пытаюсь его изучить. Также, насколько я знаю, Eclipse использует JNI для вызова JVM, верно? - person Will_Panda; 21.11.2017
comment
Вы не можете сделать это с помощью JNI, если только вы не дойдете до крайней длины создания и вызова нового ClassLoader через JNI. Это бессмысленно. Найдите что-нибудь еще, что действительно нуждается в JNI. Eclipse уже работает в JVM, поэтому либо он запускает новый процесс JVM при каждом запуске, по существу через java.lang.Process, либо делает то, что я рекомендовал выше. Java никогда не поддерживала несколько JVM в одном процессе. - person user207421; 21.11.2017
comment
Если я вызову метод loadClass в ClassLoader с помощью JNI, загрузит ли он последний файл класса или возьмет тот, который уже загружен? Потому что, если он сможет загрузить новый файл класса, это решит мой вопрос. - person Will_Panda; 21.11.2017
comment
Вам нужен новый загрузчик классов для загрузки нового файла классов. Я это уже заявлял. - person user207421; 21.11.2017

Решение, которое я использовал для этого, заключалось в создании подпроцесса, который вызывает JVM, затем делает все, что нужно, и завершает работу. Таким образом, каждый раз, когда вызывается подпроцесс, он создает новую JVM, следовательно, каждый раз загружает измененные файлы классов.

person Will_Panda    schedule 26.02.2018