Я пытаюсь установить связь из приложения Java с другой виртуальной машиной Java с помощью агента, подключенного к JVMTI (C ++).Основная идея состоит в том, чтобы подключить агент от ВМ А к ВМ В через API присоединения (https://docs.oracle.com/javase/8/docs/technotes/guides/attach/index.html) и позже связываться с агентом, чтобы он мог делегировать мои команды от ВМ А к ВМ В. У меня естьПриложение JavaFX, которое перечисляет все виртуальные машины Java (VirtualMachine.list ()) и присоединяет к ним агент. Для каждой виртуальной машины Java есть кнопка, которая должна отправить строку агенту, который подключен к соответствующей виртуальной машине.
Изображения:
![JavaFX application](https://i.stack.imgur.com/0OTx3.png)
![Configuration](https://i.stack.imgur.com/HzkCr.png)
Что ядостигнуто:
Я могу присоединить собственный агент через API присоединения к работающей виртуальной машине. Метод Agent_OnAttach выполнен, и поэтому я могу выполнить некоторые базовые проверки на виртуальной машине.B, если это подходит для моих нужд.
Проблема:
После того, как агент был подключен, я больше не могу общаться с агентом.можно подключить новый агент каждый раз, когда я хочу отправить команду VM B, но так как у меня нет возможности удалить подключенных агентов, это приведет к огромному количеству агентов, подключенных к виртуальной машине.Я также предпочел бы не использовать файлы или сокеты для связи.
Я пытался использовать JNI для связи, но я не могу настроить связь между общей библиотекой и собственным агентом.Я не нашел способа сохранить jvmtiEnv из метода Agent_OnAttach, чтобы использовать его из нативного метода.
Единственный способ решить эту проблему - это присоединить нового агента каждый раз, когда я хочуотправить команду (для которой потребуется найти способ отсоединения агента после выполнения его метода Agent_OnAttach) или выяснить, как использовать JNI для связи с агентом после подключения.
Собственный агент:
jvmtiExtensionFunction getExtensionFunction(jvmtiEnv* jvmti, const std::string& functionName) {
....
return function;
}
JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* vm, char* options, void* reserved) {
jvmtiEnv* jvmti = NULL;
// Initialize jvmti
vm->GetEnv((void**) &jvmti, JVMTI_VERSION_1_2);
std::string isVMSuitableFunctionName("vmCheckFunction");
jvmtiExtensionFunction isVMSuitableFunction = getExtensionFunction(jvmti, isVMSuitableFunctionName);
int result = 1;
if(isVMSuitableFunction != NULL) {
jboolean jIsVMSuitable;
isVMSuitableFunction(jvmti, &jIsVMSuitable);
if(jIsVMSuitable) {
result = 0;
} else {
result = 2;
}
}
return result;
}
JNIEXPORT void JNICALL Java_jni_method_tag(JNIEnv *env, jobject obj, jstring tag) {
// Communicate with the VM the agent has been attached to
}
Класс Java:
public class TaggingAgent {
public void attachToVM(String vmID, String agentPath) throws AgentAttachException {
try {
VirtualMachine machine = VirtualMachine.attach(vmID);
machine.loadAgentPath(agentPath);
machine.detach();
} catch (AgentInitializationException e) {
switch (e.returnValue()) {
case 1:
throw new AgentAttachException("JVM is not suitable.", e);
case 2:
throw new AgentAttachException("JVM doesn't support this action.", e);
default:
throw new AgentAttachException("Couldn't attach agent to JVM.", e);
}
} catch (AttachNotSupportedException | IOException | AgentLoadException e) {
throw new AgentAttachException("Couldn't attach agent to JVM.", e);
}
}
public native void tag(String tag);
}
Я уже проверял следующие вопросы:
Как связаться с агентом jvmti, подключенным к работающей JVM
Связь между агентом JVMTI и отдельным JVM
Выгрузка агента JVMTI ввремя выполнения?
но похоже, что не было найдено хорошего решения.