我在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
答案 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)。
使用自定义应用程序,您将使用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
。