Почему Java открывает 3 порта при настройке JMX?

Я запускаю свою Java-программу с JDK7 на Centos6. Я включаю JMX, используя следующие параметры:

JAVA_OPTS="${JAVA_OPTS} -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9123 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=true"

Когда я проверяю, какие порты открыты, я обнаруживаю 2 дополнительных случайных порта:

netstat -plunt | grep java
tcp        0      0 :::9123                     :::*                        LISTEN      13295/java
tcp        0      0 :::59927                    :::*                        LISTEN      13295/java
tcp        0      0 :::59928                    :::*                        LISTEN      13295/java

Обратите внимание, что при каждом перезапуске только настроенный порт 9123 остается неизменным, и два дополнительных порта меняют значения.

netstat -plunt | grep java
tcp        0      0 :::9123                     :::*                        LISTEN      13331/java
tcp        0      0 :::59932                    :::*                        LISTEN      13331/java
tcp        0      0 :::59933                    :::*                        LISTEN      13331/java

Что такое 2 дополнительных порта и почему они открыты?

Как я могу настроить 2 дополнительных случайных порта?

Как я могу настроить ::ffff:127.0.0.1 появится перед всеми портами, открытыми JMX?

Почему один порт не используется при соединении с JConsole?

Добавлено для уточнения ответа

К сожалению, дополнительный случайный порт все еще открыт. Напоминаю, что я использую Centos 6. Мои настройки Tomcat выглядят так (Tomcat не развертывает никаких приложений):

CATALINA_OPTS="${CATALINA_OPTS}  -XX:+DisableAttachMechanism -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=true -Djava.rmi.server.useLocalHostname=true -Djava.rmi.server.useCodebaseOnly=true -Dcom.sun.management.jmxremote.port=9123 -Dcom.sun.management.jmxremote.rmi.port=9123"

Процесс Tomcat выглядит следующим образом:

/usr/java/jdk1.7.0_51/bin/java -Djava.util.logging.config.file=/usr/tomcat-7.0.47/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -XX:+DisableAttachMechanism -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=true -Djava.rmi.server.useLocalHostname=true -Djava.rmi.server.useCodebaseOnly=true -Dcom.sun.management.jmxremote.port=9123 -Dcom.sun.management.jmxremote.rmi.port=9123 -Djava.endorsed.dirs=/usr/tomcat-7.0.47/endorsed -classpath /usr/tomcat-7.0.47/bin/bootstrap.jar:/usr/tomcat-7.0.47/bin/tomcat-juli.jar -Dcatalina.base=/usr/tomcat-7.0.47 -Dcatalina.home=/usr/tomcat-7.0.47 -Djava.io.tmpdir=/usr/tomcat-7.0.47/temp org.apache.catalina.startup.Bootstrap start

К сожалению, каждый раз, когда я вижу дополнительный порт прослушивания:

tcp        0      0 :::38830                    :::*                        LISTEN      790/java
tcp        0      0 ::ffff:127.0.0.1:8080       :::*                        LISTEN      790/java
tcp        0      0 :::9123                     :::*                        LISTEN      790/java

Дополнительный прогон:

tcp        0      0 ::ffff:127.0.0.1:8080       :::*                        LISTEN      2348/java
tcp        0      0 :::36252                    :::*                        LISTEN      2348/java
tcp        0      0 :::9123                     :::*                        LISTEN      2348/java

Кстати, почему я не вижу ::ffff:127.0.0.1 перед портами RMI?

Добавлен второй раз, чтобы уточнить комментарий

Это не связано с Tomcat. Я попытался запустить Ant с аналогичными настройками: процесс Ant выглядит следующим образом:

/usr/bin/java -XX:+DisableAttachMechanism -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=true -Djava.rmi.server.useLocalHostname=true -Djava.rmi.server.useCodebaseOnly=true -Dcom.sun.management.jmxremote.port=9123 -Dcom.sun.management.jmxremote.rmi.port=9123 -classpath /usr/apache-ant-1.9.2/lib/ant-launcher.jar -Dant.home=/usr/apache-ant-1.9.2 -Dant.library.dir=/usr/apache-ant-1.9.2/lib org.apache.tools.ant.launch.Launcher -cp  sleep

К сожалению, каждый раз, когда я вижу дополнительный порт прослушивания:

tcp        0      0 :::41200                    :::*                        LISTEN      13597/java
tcp        0      0 :::9123                     :::*                        LISTEN      13597/java

Дополнительный прогон:

tcp        0      0 :::58356                    :::*                        LISTEN      13629/java
tcp        0      0 :::9123                     :::*                        LISTEN      13629/java

Ответ: это ошибка Java

Мне удалось открыть ошибку на Java: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8035404

5 ответов

Решение

Вопреки распространенному мнению JMX/RMI не нужно открывать все эти порты. Вы можете фактически заставить их быть одинаковыми, что будет означать, что в конце дня вам нужно будет только пробить одну дыру в брандмауэре (если брандмауэр - ваша задача).

Попробуйте установить свойства системы:

com.sun.management.jmxremote.port
com.sun.management.jmxremote.rmi.port

к тому же значению!!

Явная установка этих параметров не позволит RMI выбирать случайные порты. Если установить для них одно и то же значение, он откроет меньше портов для прослушивания.

Это будет работать в Java 7 с обновлением 25 или позже.

Какой третий порт?

Третий порт, который вы видите открытым вашим приложением (или второй, если вы следовали моему совету выше), используется Java Attach API. Это то, что JConsole использует для подключения к "Локальному процессу". Функция Java Attach API включена по умолчанию, поскольку Java 6 независимо от com.sun.management.jmxremote имущество. Эта функция будет использовать случайный порт, но на самом деле это не имеет значения, потому что эта функция разрешает соединения только с самого хоста. Если вам действительно не нравится эта функция, вы можете добавить -XX:+DisableAttachMechanism в командной строке, чтобы отключить функцию Java Attach API. Тогда вы больше не увидите процесс Java (в данном случае Tomcat), прослушивающий случайный порт.

Как заставить JMX прослушивать только интерфейс обратной связи

С приложением, сделанным на заказ, вы должны использовать RMIServerSocketFactory, но это Tomcat, поэтому вам придется делать это с помощью JMX Remote Lifecycle Listener Tomcat.

С другой стороны, теперь не имеет значения, что у вас есть com.sun.management.jmxremote.local.only свойство начиная с Java 7. Он гарантирует, что разрешены только соединения с самого хоста. Имейте в виду, что библиотека JMX не достигает этого путем привязки к петлевому интерфейсу, что, безусловно, будет одним из способов сделать это, но также будет немного неточным, поскольку хост может иметь несколько петлевых интерфейсов.

Фактически, в целом (с самыми последними дополнениями к JDK по сравнению с JMX) я бы сказал, что JMX Remote Lifecycle Listener от Tomcat теперь избыточен, если только вы не хотите связываться с каким-то действительно странным сетевым интерфейсом.

Использование Oracle Java SE 1.8.0_121.

Можно установить одинаковые значения для jmxremote.port и jmxremote.rmi.port, но на один порт меньше. Также возможно установить jmxremote.host=127.0.0.1, чтобы этот порт (или эти два порта, если вы устанавливаете их по-разному) связывался только с интерфейсом обратной связи.

Другой порт по-прежнему назначается динамически и будет привязан к 0.0.0.0. Я не смог предотвратить этот порт с -XX+DisableAttachMechanism, а также не смог привязать его к чему-либо еще, кроме 0.0.0.0.

Поскольку jmx инкапсулирован в rmi, это очень брандмауэр, и он недружелюбен. Избегайте этого, если можете, есть альтернативная инкапсуляция, называемая jmxmp.

Посмотрите, что может вам помочь: http://blog.markfeeney.com/2010/10/jmx-through-ssh-tunnel.html http://jrds.fr/sourcetype/jmx/start

Третий порт не имеет ничего общего с тем, как работает RMI (JRMP), как неправильно указано в ошибке .

Также не имеет ничего общего с Java Attach API.

Это порт, используемый локальным слушателем JMX. Каждый раз, когда запускается удаленный JMX, по какой-то причине запускается и локальный. Это можно увидеть в этом коде из OpenJDK:

              /*
         * If the jmxremote.port property is set then we start the
         * RMIConnectorServer for remote M&M.
         *
         * If the jmxremote or jmxremote.port properties are set then
         * we start a RMIConnectorServer for local M&M. The address
         * of this "local" server is exported as a counter to the jstat
         * instrumentation buffer.
         */
        if (jmxremote != null || jmxremotePort != null) {
            if (jmxremotePort != null) {
                jmxServer = ConnectorBootstrap.
                        startRemoteConnectorServer(jmxremotePort, props);
                startDiscoveryService(props);
            }
            startLocalManagementAgent();
        }

Это также упоминается в документации :

Чтобы включить мониторинг и управление из удаленных систем, вы должны установить следующее системное свойство при запуске виртуальной машины Java: com.sun.management.jmxremote.port=portNum

В указанном выше свойстве portNum - это номер порта, через который вы хотите разрешить соединения JMX RMI. Обязательно укажите неиспользуемый номер порта. Помимо публикации коннектора RMI для локального доступа, установка этого свойства публикует дополнительный коннектор RMI в частном реестре только для чтения на указанном порте с хорошо известным именем «jmxrmi».

Также с 2020 года локальный порт можно настроить через com.sun.management.jmxremote.local.port.

Что касается проблемы, которую открыл Майкл, то это, похоже, ожидаемое поведение https://bugs.openjdk.java.net/browse/JDK-8035404

Другие вопросы по тегам