Я в java мало что понимаю, но собираюсь разбираться, и хотелось бы получить некоторые ответы.
В общем схема такая:
Java-приложение (назовем его "главное" приложение) загружает библиотеку на C++, которая грузит плагины (тоже на C++)
Далее хотелось бы из некоторых плагинов (видимо используя JNI) приаттачиться к VM из "главного" приложения и догрузить туда еще пачку JAR файлов.
Здравствуйте, Ablex, Вы писали:
A> В общем схема такая: A> Java-приложение (назовем его "главное" приложение) загружает библиотеку на C++, которая грузит плагины (тоже на C++) A> Далее хотелось бы из некоторых плагинов (видимо используя JNI) приаттачиться к VM из "главного" приложения и догрузить туда еще пачку JAR файлов.
В java не бывает никакой догрузки JAR-файлов. Есть ClassLoader-ы и они резолвят классы, отыскивая их в class paths. Как-то так.
A> Можно такое (выделенное жирным) сделать и как?
При регистрации плагина, ему нужно давать какой-то интерфейс, который они могут позвать с целью создания своего класслоадера с нужными источниками классов и т.д.
Но вообще говоря, это довольно сложный путь с кучей подводных граблей с жонглированием версиями зависимостей. Я бы лучше смотрел в сторону запуска отдельных процессов-сервисов и общению через пайпы/сокеты/shmem.
Очевидная грабля — старинный плагин хочет непременно JDK1.7, а новый плагин захочет JDK21 — и приехали.
JNI_GetCreatedJavaVMs — это что-то совсем другое, это когда из нативного кода запускаем VM. Я не понимаю как такое можно приспособить к твоей задаче.
Здравствуйте, ·, Вы писали:
·>Здравствуйте, Ablex, Вы писали: ·>Но вообще говоря, это довольно сложный путь с кучей подводных граблей с жонглированием версиями зависимостей. Я бы лучше смотрел в сторону запуска отдельных процессов-сервисов и общению через пайпы/сокеты/shmem. ·>Очевидная грабля — старинный плагин хочет непременно JDK1.7, а новый плагин захочет JDK21 — и приехали.
Зачем плагину JDK ? Он же на С++ написан.
Надо получить JavaVM **vm в JNI-библиотеке, а потом то ли из нее, то ли из плагина попросить Java VM (вызвать какой-то метод?) загрузить jar через ClassLoader, как в той ссылке, что ты привел.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Надо получить JavaVM **vm в JNI-библиотеке, а потом то ли из нее, то ли из плагина попросить Java VM (вызвать какой-то метод?) загрузить jar через ClassLoader, как в той ссылке, что ты привел.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD> A>Если ещё появятся еще какие-то комментарии, то буду благодарен. PD> Похоже, вот то, что тебе нужно
Похоже, что нет. У него java-приложение (назовем его "главное" приложение) загружает библиотеку на C++, а по твоей ссылке с точностью до наоборот: C++ приложение загружает JVM.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD> ·>Очевидная грабля — старинный плагин хочет непременно JDK1.7, а новый плагин захочет JDK21 — и приехали. PD> Зачем плагину JDK ? Он же на С++ написан.
Он сказал, что плагин хочет загрузить какие-то свои дополнительные java-классы, которых нет в "главном приложении" которое уже запущено. Эти самые java-классы могут быть не совместимы с JDK, под которым работает его главное приложение.
PD> Надо получить JavaVM **vm в JNI-библиотеке, а потом то ли из нее, то ли из плагина попросить Java VM (вызвать какой-то метод?)
Накой ему **vm? И что за метод-то ты предлагаешь вызвать-то?
PD> загрузить jar через ClassLoader, как в той ссылке, что ты привел.
Выражайся точнее. jar не загружается. Загружаются классы из различных источников (возможно из jar-ов). И динамически менять classpath нельзя (если исключить грязные хаки).
Здравствуйте, ·, Вы писали:
·>Похоже, что нет. У него java-приложение (назовем его "главное" приложение) загружает библиотеку на C++, а по твоей ссылке с точностью до наоборот: C++ приложение загружает JVM.
Да, но скорее всего основная замена — это JNI_CreateJavaVM на GetJavaVM.
ТС нужно не создавать и запускать JVM , а добраться к JVM, которая вызвала его JNI. А остальное все так же.
Здравствуйте, ·, Вы писали:
PD>> Зачем плагину JDK ? Он же на С++ написан. ·>Он сказал, что плагин хочет загрузить какие-то свои дополнительные java-классы, которых нет в "главном приложении" которое уже запущено. Эти самые java-классы могут быть не совместимы с JDK, под которым работает его главное приложение.
Нет. Цитирую его
которая грузит плагины (тоже на C++)
Далее хотелось бы из некоторых плагинов (видимо используя JNI) приаттачиться к VM из "главного" приложения и догрузить туда еще пачку JAR файлов.
Приаттачиться к VM и попросить ее догрузить. Ее (то есть java в ней), а вовсе не самому плагину это делать.
PD>> Надо получить JavaVM **vm в JNI-библиотеке, а потом то ли из нее, то ли из плагина попросить Java VM (вызвать какой-то метод?) ·>Накой ему **vm? И что за метод-то ты предлагаешь вызвать-то?
Какого-то класса из java приложения (не из этих jar, а из основного java приложения), который и будет все это делать. По ссылке есть примеры как это делать.
PD>> загрузить jar через ClassLoader, как в той ссылке, что ты привел. ·>Выражайся точнее. jar не загружается. Загружаются классы из различных источников (возможно из jar-ов). И динамически менять classpath нельзя (если исключить грязные хаки).
Здравствуйте, Pavel Dvorkin, Вы писали:
PD> ·>Похоже, что нет. У него java-приложение (назовем его "главное" приложение) загружает библиотеку на C++, а по твоей ссылке с точностью до наоборот: C++ приложение загружает JVM. PD> Да, но скорее всего основная замена — это JNI_CreateJavaVM на GetJavaVM. PD> ТС нужно не создавать и запускать JVM , а добраться к JVM, которая вызвала его JNI. А остальное все так же.
"Всё так же" что конкретно??? Ну вот есть у него *vm. И?
Единственное что можно существенного делать с этим — это GetEnv, но *env и так передаётся первым аргументом в каждый нативный метод.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD> Нет. Цитирую его PD> которая грузит плагины (тоже на C++) PD> Далее хотелось бы из некоторых плагинов (видимо используя JNI) приаттачиться к VM из "главного" приложения и догрузить туда еще пачку JAR файлов. PD> Приаттачиться к VM и попросить ее догрузить. Ее (то есть java в ней), а вовсе не самому плагину это делать.
На что я и ответил, что такого понятия как "догрузить туда еще пачку JAR" в VM не существует в спеке Явы. Ну, по крайней мере, я не в курсе.
PD> ·>Накой ему **vm? И что за метод-то ты предлагаешь вызвать-то? PD> Какого-то класса из java приложения (не из этих jar, а из основного java приложения), который и будет все это делать. По ссылке есть примеры как это делать.
По ссылке пример как запустить новую VM с данным optionString = "-Djava.class.path=.". Поменять это после запуска нельзя, нет такого API. Это по сути command line args, аналог java.exe -Djava.class.path=..
Здравствуйте, ·, Вы писали:
·>Здравствуйте, Pavel Dvorkin, Вы писали:
·>"Всё так же" что конкретно??? Ну вот есть у него *vm. И?
jint GetJavaVM(JNIEnv *env, JavaVM **vm);
Returns the Java VM interface (used in the Invocation API) associated with the current thread. The result is placed at the location pointed to by the second argument, vm.
Здравствуйте, ·, Вы писали:
PD>> Приаттачиться к VM и попросить ее догрузить. Ее (то есть java в ней), а вовсе не самому плагину это делать. ·>На что я и ответил, что такого понятия как "догрузить туда еще пачку JAR" в VM не существует в спеке Явы. Ну, по крайней мере, я не в курсе.
Ты же сам дал ссылку на то, как через classpath их добавить.
Вот еще пример, как добавить, правда, какой-то сабкласс, но это едва ли существенно.
https://stackabuse.com/example-loading-a-java-class-at-runtime/
PD>> Какого-то класса из java приложения (не из этих jar, а из основного java приложения), который и будет все это делать. По ссылке есть примеры как это делать. ·>По ссылке пример как запустить новую VM с данным optionString = "-Djava.class.path=.". Поменять это после запуска нельзя, нет такого API. Это по сути command line args, аналог java.exe -Djava.class.path=..
Здравствуйте, Pavel Dvorkin, Вы писали:
PD> ·>На что я и ответил, что такого понятия как "догрузить туда еще пачку JAR" в VM не существует в спеке Явы. Ну, по крайней мере, я не в курсе. PD> Ты же сам дал ссылку на то, как через classpath их добавить. PD> Вот еще пример, как добавить, правда, какой-то сабкласс, но это едва ли существенно. PD> https://stackabuse.com/example-loading-a-java-class-at-runtime/
Так ведь тут не приаттачиться к VM из "главного" приложения и догрузить туда еще пачку JAR, а создать новый класслоадер с новыми источниками классов. Разница принципиальная.
PD> Ответил в другом ответе.
"Ну может, тогда и не нужен GetJavaVM" — верно, что я сразу и сказал.
PD> А что делать — jclass cls2 = env->FindClass("MyTest"); // try to find the class
ИЧСХ тут никакого "догрузить туда еще пачку JAR" нет. Классы будут искаться только из текущей запущенной VM, ничего догруженного тут быть не может.
Здравствуйте, ·, Вы писали:
·>Так ведь тут не приаттачиться к VM из "главного" приложения и догрузить туда еще пачку JAR, а создать новый класслоадер с новыми источниками классов. Разница принципиальная.
Ну и что ? Надо как-то из C/C++ библиотеки/плугина вызывать некий метод из java класса, а он пусть делает то, что в
public C LoadClass(String directory, String classpath, Class<C> parentClass) throws ClassNotFoundException {
Надо новый класслоадер делать — пусть делает, какая разница ?
·>"Ну может, тогда и не нужен GetJavaVM" — верно, что я сразу и сказал.
Я в первом же ответе написал, что отнюдь не специалист по JNI. И то, что JNIEnv передается в любой метод, я просто не знал. Если так, то все еще проще.
PD>> А что делать — jclass cls2 = env->FindClass("MyTest"); // try to find the class ·>ИЧСХ тут никакого "догрузить туда еще пачку JAR" нет. Классы будут искаться только из текущей запущенной VM, ничего догруженного тут быть не может.
Ну тут я не понимаю. Я же дал ссылку, где из directory их загружают.
Here is some code that will help you dynamically load a new class given the path to its jar file.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD> ·>Так ведь тут не приаттачиться к VM из "главного" приложения и догрузить туда еще пачку JAR, а создать новый класслоадер с новыми источниками классов. Разница принципиальная. PD> Ну и что ? Надо как-то из C/C++ библиотеки/плугина вызывать некий метод из java класса, а он пусть делает то, что в
Ну в общем да. Это я и сказал в самом начале: "При регистрации плагина, ему нужно давать какой-то интерфейс, который они могут позвать с целью создания своего класслоадера с нужными источниками классов и т.д.". Т.е. плагин должен просто подёргать некие java-методы, как обычно. Загрузка классов никакого отношения к сабж не имеет.
PD> Надо новый класслоадер делать — пусть делает, какая разница ?
Что это ничего в classpath VM не догружает. Это такой специальный system classpath, иммутабельный.
PD> ·>"Ну может, тогда и не нужен GetJavaVM" — верно, что я сразу и сказал. PD> Я в первом же ответе написал, что отнюдь не специалист по JNI. И то, что JNIEnv передается в любой метод, я просто не знал. Если так, то все еще проще.
Именно. Поэтому твои рекомендации использовать GetJavaVM не в ту степь.
PD> Там неверно ?
Верно, но к JNI никакого отношения не имеет.
Здравствуйте, ·, Вы писали:
·>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>> ·>Так ведь тут не приаттачиться к VM из "главного" приложения и догрузить туда еще пачку JAR, а создать новый класслоадер с новыми источниками классов. Разница принципиальная. PD>> Ну и что ? Надо как-то из C/C++ библиотеки/плугина вызывать некий метод из java класса, а он пусть делает то, что в ·>Ну в общем да. Это я и сказал в самом начале: "При регистрации плагина, ему нужно давать какой-то интерфейс, который они могут позвать с целью создания своего класслоадера с нужными источниками классов и т.д.". Т.е. плагин должен просто подёргать некие java-методы, как обычно. Загрузка классов никакого отношения к сабж не имеет.
Не имеет. Это потом этот метод и должен делать.
PD>> Надо новый класслоадер делать — пусть делает, какая разница ? ·>Что это ничего в classpath VM не догружает. Это такой специальный system classpath, иммутабельный.
Да ради бога, не имеет значения. Важно, что можно в конечном счете сделать то, что нужно ТС.
PD>> ·>"Ну может, тогда и не нужен GetJavaVM" — верно, что я сразу и сказал. PD>> Я в первом же ответе написал, что отнюдь не специалист по JNI. И то, что JNIEnv передается в любой метод, я просто не знал. Если так, то все еще проще. ·>Именно. Поэтому твои рекомендации использовать GetJavaVM не в ту степь.
Равно как и твои насчет версий JDK .
PD>> Там неверно ? ·>Верно, но к JNI никакого отношения не имеет.
В общем, похоже, мы говорим об одном и том же. Суть от этого не меняется. Про то, что JVM не нужна — уже написал раньше.
Сама задача , видимо, решается.
С остальным пусть ТС сам разбирается. Думаю, мы вдвоем дали ему достаточно материала для дальнейших изысканий.