为何在配置JMX时Java打开3个端口?

时间:2014-01-02 13:43:41

标签: java rmi jmx

我在Centos6上使用JDK7运行我的Java程序。我使用以下选项启用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"

当我检查打开了哪些端口时,我发现了另外两个随机端口:

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个额外的随机端口?

如何在JMX打开所有端口之前配置::ffff:127.0.0.1

为什么在与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

BTW,为什么我在RMI端口之前看不到::ffff:127.0.0.1

第二次添加澄清评论

它与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上的bug: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8035404

4 个答案:

答案 0 :(得分:96)

与普遍看法相反,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,因此您必须使用Tomcat的JMX Remote Lifecycle Listener进行此操作。

另一方面,自Java 7以来你拥有com.sun.management.jmxremote.local.only属性并不重要。它确保只允许来自主机本身的连接。请注意,JMX库没有通过绑定到loopback接口来实现这一点,而loopback接口肯定是一种方式,但由于主机可能有多个环回接口,因此也会略有不准确。

事实上大体上(最近添加了JDK和JMX)我会说Tomcat的 JMX远程生命周期监听器现在是多余的,除非你想要绑定到一些非常奇怪的网络接口

答案 1 :(得分:3)

使用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之外的其他任何内容。

答案 2 :(得分:2)

因为jmx封装在rmi中,所以防火墙非常不友好。如果可以,请避免使用,有一种名为jmxmp的替代封装。

看看,这可能对您有所帮助: http://blog.markfeeney.com/2010/10/jmx-through-ssh-tunnel.html http://jrds.fr/sourcetype/jmx/start#jmx_protocols

答案 3 :(得分:0)

第三个端口与 RMI (JRMP) 的工作方式无关,如错误注明的 in the bug

也与 Java Attach API 无关。

它是本地 JMX 侦听器使用的端口。每当启动远程 JMX 时,出于某种原因,本地 JMX 也会启动。这可以在此code from 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();
        }

还提到了in the documentation

<块引用>

要启用远程系统的监控和管理,您必须设置 启动 Java VM 时的以下系统属性:com.sun.management.jmxremote.port=portNum

在上面的属性中,portNum 是您要通过其启用 JMX RMI 的端口号 连接。请务必指定未使用的端口号。 除了 发布用于本地访问的 RMI 连接器,设置此属性 在私有只读注册表中发布额外的 RMI 连接器 在指定端口使用众所周知的名称“jmxrmi”。

此外,自 2020 年以来,本地端口 can be configured 通过 com.sun.management.jmxremote.local.port