JNI Attach
От: Ablex  
Дата: 04.11.24 11:36
Оценка:
Здрасьте)

Я в java мало что понимаю, но собираюсь разбираться, и хотелось бы получить некоторые ответы.

В общем схема такая:
Java-приложение (назовем его "главное" приложение) загружает библиотеку на C++, которая грузит плагины (тоже на C++)
Далее хотелось бы из некоторых плагинов (видимо используя JNI) приаттачиться к VM из "главного" приложения и догрузить туда еще пачку JAR файлов.

Можно такое (выделенное жирным) сделать и как?
Re: JNI Attach
От: Ablex  
Дата: 04.11.24 11:51
Оценка:
A>Можно такое (выделенное жирным) сделать и как?

JNI_GetCreatedJavaVMs — оно?
Re[2]: JNI Attach
От: Pavel Dvorkin Россия  
Дата: 04.11.24 12:18
Оценка: 2 (1)
Здравствуйте, Ablex, Вы писали:

A>JNI_GetCreatedJavaVMs — оно?


Я отнюдь не специалист по JNI.

Думаю, что скорее GetJavaVM

https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#GetJavaVM

Посмотри здесь

https://stackoverflow.com/questions/12900695/how-to-obtain-jni-interface-pointer-jnienv-for-asynchronous-calls
With best regards
Pavel Dvorkin
Re[3]: JNI Attach
От: Ablex  
Дата: 04.11.24 12:24
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Посмотри здесь


PD>https://stackoverflow.com/questions/12900695/how-to-obtain-jni-interface-pointer-jnienv-for-asynchronous-calls


Спасибо! Буду разбираться.

Нашёл ещё вот такой способ:
https://stackoverflow.com/questions/50246855/get-java-vm-pointer-in-global-object-constructor-in-android-native-code-before-j

Если ещё появятся еще какие-то комментарии, то буду благодарен.
Re: JNI Attach
От: · Великобритания  
Дата: 04.11.24 12:25
Оценка: 2 (1) +1
Здравствуйте, Ablex, Вы писали:

A> В общем схема такая:

A> Java-приложение (назовем его "главное" приложение) загружает библиотеку на C++, которая грузит плагины (тоже на C++)
A> Далее хотелось бы из некоторых плагинов (видимо используя JNI) приаттачиться к VM из "главного" приложения и догрузить туда еще пачку JAR файлов.
В java не бывает никакой догрузки JAR-файлов. Есть ClassLoader-ы и они резолвят классы, отыскивая их в class paths. Как-то так.

A> Можно такое (выделенное жирным) сделать и как?

При регистрации плагина, ему нужно давать какой-то интерфейс, который они могут позвать с целью создания своего класслоадера с нужными источниками классов и т.д.

Но вообще говоря, это довольно сложный путь с кучей подводных граблей с жонглированием версиями зависимостей. Я бы лучше смотрел в сторону запуска отдельных процессов-сервисов и общению через пайпы/сокеты/shmem.
Очевидная грабля — старинный плагин хочет непременно JDK1.7, а новый плагин захочет JDK21 — и приехали.

JNI_GetCreatedJavaVMs — это что-то совсем другое, это когда из нативного кода запускаем VM. Я не понимаю как такое можно приспособить к твоей задаче.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[4]: JNI Attach
От: Pavel Dvorkin Россия  
Дата: 04.11.24 12:27
Оценка: 2 (1)
Здравствуйте, Ablex, Вы писали:


A>Если ещё появятся еще какие-то комментарии, то буду благодарен.


Похоже, вот то, что тебе нужно

https://www.codeproject.com/Articles/993067/Calling-Java-from-Cplusplus-with-JNI
With best regards
Pavel Dvorkin
Re[2]: JNI Attach
От: Pavel Dvorkin Россия  
Дата: 04.11.24 12:45
Оценка: 2 (1) +1
Здравствуйте, ·, Вы писали:

·>Здравствуйте, Ablex, Вы писали:

·>Но вообще говоря, это довольно сложный путь с кучей подводных граблей с жонглированием версиями зависимостей. Я бы лучше смотрел в сторону запуска отдельных процессов-сервисов и общению через пайпы/сокеты/shmem.
·>Очевидная грабля — старинный плагин хочет непременно JDK1.7, а новый плагин захочет JDK21 — и приехали.

Зачем плагину JDK ? Он же на С++ написан.

Надо получить JavaVM **vm в JNI-библиотеке, а потом то ли из нее, то ли из плагина попросить Java VM (вызвать какой-то метод?) загрузить jar через ClassLoader, как в той ссылке, что ты привел.
With best regards
Pavel Dvorkin
Re[3]: JNI Attach
От: Ablex  
Дата: 04.11.24 12:50
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Надо получить JavaVM **vm в JNI-библиотеке, а потом то ли из нее, то ли из плагина попросить Java VM (вызвать какой-то метод?) загрузить jar через ClassLoader, как в той ссылке, что ты привел.


Да, вы всё верно понимаете.
Re[5]: JNI Attach
От: · Великобритания  
Дата: 04.11.24 13:05
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD> A>Если ещё появятся еще какие-то комментарии, то буду благодарен.

PD> Похоже, вот то, что тебе нужно
Похоже, что нет. У него java-приложение (назовем его "главное" приложение) загружает библиотеку на C++, а по твоей ссылке с точностью до наоборот: C++ приложение загружает JVM.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[3]: JNI Attach
От: · Великобритания  
Дата: 04.11.24 13:13
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD> ·>Очевидная грабля — старинный плагин хочет непременно JDK1.7, а новый плагин захочет JDK21 — и приехали.

PD> Зачем плагину JDK ? Он же на С++ написан.
Он сказал, что плагин хочет загрузить какие-то свои дополнительные java-классы, которых нет в "главном приложении" которое уже запущено. Эти самые java-классы могут быть не совместимы с JDK, под которым работает его главное приложение.

PD> Надо получить JavaVM **vm в JNI-библиотеке, а потом то ли из нее, то ли из плагина попросить Java VM (вызвать какой-то метод?)

Накой ему **vm? И что за метод-то ты предлагаешь вызвать-то?

PD> загрузить jar через ClassLoader, как в той ссылке, что ты привел.

Выражайся точнее. jar не загружается. Загружаются классы из различных источников (возможно из jar-ов). И динамически менять classpath нельзя (если исключить грязные хаки).
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: JNI Attach
От: Pavel Dvorkin Россия  
Дата: 04.11.24 13:15
Оценка: +1
Здравствуйте, ·, Вы писали:

·>Похоже, что нет. У него java-приложение (назовем его "главное" приложение) загружает библиотеку на C++, а по твоей ссылке с точностью до наоборот: C++ приложение загружает JVM.


Да, но скорее всего основная замена — это JNI_CreateJavaVM на GetJavaVM.
ТС нужно не создавать и запускать JVM , а добраться к JVM, которая вызвала его JNI. А остальное все так же.
With best regards
Pavel Dvorkin
Re[4]: JNI Attach
От: Pavel Dvorkin Россия  
Дата: 04.11.24 13:21
Оценка:
Здравствуйте, ·, Вы писали:

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 нельзя (если исключить грязные хаки).

Спасибо за уточнение терминологии.
With best regards
Pavel Dvorkin
Отредактировано 04.11.2024 13:21 Pavel Dvorkin . Предыдущая версия .
Re[7]: JNI Attach
От: · Великобритания  
Дата: 04.11.24 13:29
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD> ·>Похоже, что нет. У него java-приложение (назовем его "главное" приложение) загружает библиотеку на C++, а по твоей ссылке с точностью до наоборот: C++ приложение загружает JVM.

PD> Да, но скорее всего основная замена — это JNI_CreateJavaVM на GetJavaVM.
PD> ТС нужно не создавать и запускать JVM , а добраться к JVM, которая вызвала его JNI. А остальное все так же.
"Всё так же" что конкретно??? Ну вот есть у него *vm. И?

Единственное что можно существенного делать с этим — это GetEnv, но *env и так передаётся первым аргументом в каждый нативный метод.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[5]: JNI Attach
От: · Великобритания  
Дата: 04.11.24 13:35
Оценка:
Здравствуйте, 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=..
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[8]: JNI Attach
От: Pavel Dvorkin Россия  
Дата: 04.11.24 13:42
Оценка:
Здравствуйте, ·, Вы писали:

·>Здравствуйте, 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.

https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#GetJavaVM

·>Единственное что можно существенного делать с этим — это GetEnv, но *env и так передаётся первым аргументом в каждый нативный метод.


Ну может, тогда и не нужен GetJavaVM, раз и так передается.

А что делать —



jclass cls2 = env->FindClass("MyTest");  // try to find the class
if(cls2 == nullptr) {
    cerr << "ERROR: class not found !";
}
else {                                  // if class found, continue
    cout << "Class MyTest found" << endl;
    jmethodID mid = env->GetStaticMethodID(cls2, "mymain", "()V");  // find method
    if(mid == nullptr)
        cerr << "ERROR: method void mymain() not found !" << endl;
    else {
        env->CallStaticVoidMethod(cls2, mid);                      // call method
        cout << endl;
    }

}

https://www.codeproject.com/Articles/993067/Calling-Java-from-Cplusplus-with-JNI
With best regards
Pavel Dvorkin
Re[6]: JNI Attach
От: Pavel Dvorkin Россия  
Дата: 04.11.24 13:47
Оценка:
Здравствуйте, ·, Вы писали:

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=..

Ответил в другом ответе.
With best regards
Pavel Dvorkin
Re[7]: JNI Attach
От: · Великобритания  
Дата: 04.11.24 14:00
Оценка:
Здравствуйте, 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, ничего догруженного тут быть не может.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[8]: JNI Attach
От: Pavel Dvorkin Россия  
Дата: 04.11.24 14:08
Оценка:
Здравствуйте, ·, Вы писали:

·>Так ведь тут не приаттачиться к 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.

https://stackabuse.com/example-loading-a-java-class-at-runtime/

Там неверно ?
With best regards
Pavel Dvorkin
Отредактировано 04.11.2024 14:09 Pavel Dvorkin . Предыдущая версия .
Re[9]: JNI Attach
От: · Великобритания  
Дата: 04.11.24 14:23
Оценка: 2 (1)
Здравствуйте, Pavel Dvorkin, Вы писали:

PD> ·>Так ведь тут не приаттачиться к VM из "главного" приложения и догрузить туда еще пачку JAR, а создать новый класслоадер с новыми источниками классов. Разница принципиальная.

PD> Ну и что ? Надо как-то из C/C++ библиотеки/плугина вызывать некий метод из java класса, а он пусть делает то, что в
Ну в общем да. Это я и сказал в самом начале: "При регистрации плагина, ему нужно давать какой-то интерфейс, который они могут позвать с целью создания своего класслоадера с нужными источниками классов и т.д.". Т.е. плагин должен просто подёргать некие java-методы, как обычно. Загрузка классов никакого отношения к сабж не имеет.

PD> Надо новый класслоадер делать — пусть делает, какая разница ?

Что это ничего в classpath VM не догружает. Это такой специальный system classpath, иммутабельный.

PD> ·>"Ну может, тогда и не нужен GetJavaVM" — верно, что я сразу и сказал.

PD> Я в первом же ответе написал, что отнюдь не специалист по JNI. И то, что JNIEnv передается в любой метод, я просто не знал. Если так, то все еще проще.
Именно. Поэтому твои рекомендации использовать GetJavaVM не в ту степь.

PD> Там неверно ?

Верно, но к JNI никакого отношения не имеет.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[10]: JNI Attach
От: Pavel Dvorkin Россия  
Дата: 04.11.24 14:37
Оценка: 2 (1)
Здравствуйте, ·, Вы писали:

·>Здравствуйте, 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 не нужна — уже написал раньше.

Сама задача , видимо, решается.

С остальным пусть ТС сам разбирается. Думаю, мы вдвоем дали ему достаточно материала для дальнейших изысканий.
With best regards
Pavel Dvorkin
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.