Как выгрузить JVM из живого процесса?

Я работаю с JNI и пытаюсь выгрузить (уничтожить) виртуальную машину с помощью функции DestoryJavaVM (сначала я вызываю метод DetachCurrentThread). Похоже, что теперь он влияет на виртуальную машину и все еще работает после вызова. Я читал в старых сообщениях Sun, что у DestoryJavaVM были проблемы в прошлом (JDK1.1-1.3 в 2001 году), но я использую JRE 6, и теперь она, вероятно, должна работать, верно? Мне нужно загрузить\выгрузить виртуальную машину в одном и том же живом процессе, поскольку для каждой загрузки требуется загрузка других классов. Любые идеи, как это можно сделать?

Дополнительная информация:

На этапе выгрузки я могу успешно detachCurrentThread и destroyVM (оба возвращают JNI_OK). Я даже FreeLibray (jvm.dll) успешно (возврат 1). Когда я снова пытаюсь загрузить JVM, я могу LoadLibrary(), затем нахожу функцию CreateVM в DLL, и вызов CreateVM терпит неудачу (возврат -1). Что я здесь делаю неправильно?

Спасибо, Гай


person Guy    schedule 06.06.2010    source источник


Ответы (4)


Хотя это не ответит на ваш вопрос о DestroyJavaVM.

OSGi приходит мне на ум, вы можете поместить все классы в пакет, активировать его, запустить код и деактивировать его, позже вы будете использовать другой пакет. См. Apache Felix.

Другим менее элегантным вариантом было бы выйти из виртуальной машины и перезапустить ее с другим путем к классам.

person stacker    schedule 06.06.2010
comment
Я не собираюсь решать OSGi, извините. Пожалуйста, ознакомьтесь с дополнительной информацией, возможно, вы можете помочь. - person Guy; 07.06.2010

Вы можете проверить ошибочные темы. API вызова: выгрузка виртуальной машины упоминает: «ВМ ждет, пока текущий поток не станет единственным пользовательским потоком, не являющимся демоном, прежде чем он действительно выгрузится». Этого требует Спецификация языка Java, 12.8.

person trashgod    schedule 07.06.2010
comment
И это может создать проблему для достаточно сложного приложения, где у вас нет полного контроля над всеми потоками (то есть сторонними библиотеками). Я бы сказал, что лучше перепроектировать, чтобы JVM перезагрузила классы (например, OSGi). Тем не менее, это, вероятно, отвечает на вопрос ОП. - person Kevin Brock; 07.06.2010
comment
Я использую JRE 1.6, поэтому Destroy должен работать. Смотрите мою дополнительную информацию, которую я добавил к своему исходному сообщению. - person Guy; 07.06.2010
comment
@Guy: Вы упомянули, что второй вызов JNI_CreateJavaVM() возвращает -1. Что говорит ExceptionOccurred()? - person trashgod; 07.06.2010
comment
@trashgod: как я могу env-›ExceptionOccurred(), когда создание JVM не удалось? env должен быть инициализирован CreateVM, я что-то пропустил? - person Guy; 08.06.2010
comment
@trashgod: я вижу, что возвращаемый код ошибки -1 (JNI_ERR), что является неизвестной ошибкой. - person Guy; 08.06.2010
comment
@Guy: Если предположить, что ваш первый вызов JNI_CreateJavaVM() прошел успешно, есть ли какие-то отличия в подготовке второго вызова? - person trashgod; 08.06.2010
comment
@trashgod: Нет, не совсем. снова вызывая тот же класс/функции. - person Guy; 09.06.2010
comment
@Guy: Извините, я в замешательстве. Я получаю аналогичный результат, если пытаюсь вызвать JNI_CreateJavaVM во второй раз, но повторно использовать тот, который только что вышел, не проблема. - person trashgod; 09.06.2010

DestroyJavaVM() не поддерживает Выгрузка ВМ.

Уничтожить JavaVM

Выгружает виртуальную машину Java и освобождает ее ресурсы.

Любой поток, присоединенный или нет, может вызвать эту функцию. Если текущий поток присоединен, виртуальная машина ожидает, пока текущий поток не станет единственным потоком Java пользовательского уровня, не являющимся демоном. Если текущий поток не присоединен, виртуальная машина присоединяет текущий поток, а затем ждет, пока текущий поток не станет единственным потоком пользовательского уровня, не являющимся демоном.

[...]

Выгрузка ВМ не поддерживается.

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

person Sundae    schedule 28.08.2014

Для новичков, посещающих этот вопрос, см. Вызов функции JNI_CreateJavaVM дважды

Краткий ответ: вы НЕ МОЖЕТЕ создать более одной JVM в одном процессе (это предусмотрено дизайном).

person XOR    schedule 25.02.2021