Связь между виртуальными машинами Java через собственный агент JVMTI - PullRequest
0 голосов
/ 11 мая 2018

Я пытаюсь установить связь из приложения Java с другой виртуальной машиной Java с помощью агента, подключенного к JVMTI (C ++).Основная идея состоит в том, чтобы подключить агент от ВМ А к ВМ В через API присоединения (https://docs.oracle.com/javase/8/docs/technotes/guides/attach/index.html) и позже связываться с агентом, чтобы он мог делегировать мои команды от ВМ А к ВМ В. У меня естьПриложение JavaFX, которое перечисляет все виртуальные машины Java (VirtualMachine.list ()) и присоединяет к ним агент. Для каждой виртуальной машины Java есть кнопка, которая должна отправить строку агенту, который подключен к соответствующей виртуальной машине.

Изображения:

JavaFX application

Configuration

Что ядостигнуто:

Я могу присоединить собственный агент через 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 ввремя выполнения?

но похоже, что не было найдено хорошего решения.

...