Аргументы среды выполнения JVM для JMX

У меня есть код, подключающийся к JMX и получающий mBean по имени. Сейчас я пишу для него тесты на JUnit. Я уже провел несколько тестов без аутентификации, используя что-то вроде этого:

private static void startJmxServer() throws Exception {
  MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

  LocateRegistry.createRegistry(PORT);

  JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + HOST + ':' + PORT + "/jmxrmi");
  JMXConnectorServer connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);

  Example exampleMBean = new Example();
  ObjectName exampleName = new ObjectName(MBEAN_NAME);

  mbs.registerMBean(exampleMBean, exampleName);

  connectorServer.start();
} 

Теперь я хочу провести тест с аутентификацией. Поэтому мне нужно указать следующие свойства JVM:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=1234
-Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.access.file=/somepath/jmxremote.access
-Dcom.sun.management.jmxremote.password.file=/somepath/jmxremote.password

Я уже пытался передать эти свойства в переменную окружения JMXConnectorServer. Также я пробовал System.setProperty. Но не удалось, так как подключение было доступно без каких-либо учетных данных. Единственный способ, который заставляет это работать:

private static void startJmxServer() throws Exception {
    String name = ManagementFactory.getRuntimeMXBean().getName();
    VirtualMachine vm = VirtualMachine.attach(name.substring(0, name.indexOf('@')));

    String lca = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");

    if (lca == null) {
        Path p = Paths.get(System.getProperty("java.home")).normalize();

        if (!"jre".equals(p.getName(p.getNameCount() - 1).toString()
            .toLowerCase())) {
            p = p.resolve("jre");
        }

        File f = p.resolve("lib").resolve("management-agent.jar").toFile();

        if (!f.exists()) {
            throw new IOException("Management agent not found");
        }

        String options = String.format("com.sun.management.jmxremote.port=%d, " +
            "com.sun.management.jmxremote.authenticate=true, " +
            "com.sun.management.jmxremote.ssl=false, " +
            "com.sun.management.jmxremote.access.file=/somepath/jmxremote.access, " +
            "com.sun.management.jmxremote.password.file=/somepath/jmxremote.password", PORT);
        vm.loadAgent(f.getCanonicalPath(), options);
    }

    vm.detach();

    MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

    Example exampleMBean = new Example();

    ObjectName exampleName = new ObjectName(MBEAN_NAME);
    mbs.registerMBean(exampleMBean, exampleName);
}

Но поскольку агент был загружен, я не могу изменить свойства виртуальной машины для запуска теста без аутентификации. Также я хочу избежать такого рода вещей из-за необходимости ручного определения tools.jar и хочу использовать общие инструменты JMX. Любая идея, как управлять этим?


person Filipp Shestakov    schedule 29.03.2016    source источник


Ответы (1)


Конфигурация аутентификации передается в environment — втором аргументе JMXConnectorServerFactory.newJMXConnectorServer.

    HashMap<String, Object> env = new HashMap<>();
    env.put("jmx.remote.x.password.file", "/somepath/jmxremote.password");
    env.put("jmx.remote.x.access.file", "/somepath/jmxremote.access");

    JMXConnectorServer connectorServer =
        JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);

Обратите внимание, что имена атрибутов здесь отличаются от имен свойств.

Обратитесь к ConnectorBootstrap.java из исходников JDK, чтобы узнать, как инициализируется JMXConnectorServer по умолчанию.

person apangin    schedule 29.03.2016
comment
Большое спасибо! Ты сделал мой день! Я пытался использовать те же имена свойств в атрибутах среды. Но теперь все работает так, как ожидалось. - person Filipp Shestakov; 29.03.2016