1. 概述
在本教程中,我们将解释为什么JMX在启动时打开三个端口。此外,我们将展示如何在Java中启动JMX。之后,我们将展示如何限制打开的端口数。
2. JMX定义
让我们首先定义什么是JMX框架。Java Management Extensions(JMX)框架为管理Java应用程序提供了一个可配置、可伸缩且可靠的基础结构。此外,它还为应用程序的实时管理定义了MBean的概念。该框架允许在本地或远程管理应用程序。
3. 在Java中启用JMX
现在让我们来看看如何启用JMX,对于Java 1.5及之前的版本,有一个系统属性com.sun.management.jmxremote。使用该属性启动的应用程序允许从本地和远程连接JConsole。另一方面,在没有该属性的情况下启动应用程序时,从JConsole中是不可见的。
但是,从Java 6及以上版本开始,该参数就不再需要了。启动后,应用程序自动可用于管理。此外,默认配置会自动分配端口并仅在本地公开。
4. JMX端口
在我们的示例中,我们将使用Java 6或更高版本。首先,让我们创建一个具有无限循环的类,该类什么都不做,但它允许我们检查打开了哪些端口:
public class JMXConfiguration {
public static void main(String[] args) {
while (true) {
// to ensure application does not terminate
}
}
}
现在,我们将编译类并启动它:
java cn.tuyucheng.taketoday.jmx.JMXConfiguration
之后,我们可以检查分配给进程的pid并检查进程打开的端口:
netstat -ao | grep <pid>
结果,我们将获得应用程序公开的端口列表:
Active Connections
Proto Local Address Foreign Address State PID
TCP 127.0.0.1:55846 wujek:55845 ESTABLISHED 2604
此外,在重启的情况下,端口将会改变,它是随机分配的。此功能从Java 6开始可用,它自动为Java Attach API公开应用程序。换句话说,它通过本地进程自动公开JConsole连接的应用程序。
现在让我们通过向JVM提供选项来启用远程连接:
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=1234
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
端口号是我们必须提供的强制参数,以便为远程连接公开JMX。我们仅出于测试目的禁用身份验证和SSL。
现在,netstat命令返回:
Proto Local Address Foreign Address State PID
TCP 0.0.0.0:1234 wujek:0 LISTENING 11088
TCP 0.0.0.0:58738 wujek:0 LISTENING 11088
TCP 0.0.0.0:58739 wujek:0 LISTENING 11088
如我们所见,该应用程序公开了三个端口。RMI/JMX公开了两个端口,第三个是用于本地连接的随机端口。
5. 限制开放端口数
首先,我们可以使用-XX:+DisableAttachMechanism选项禁用从JConsole公开本地连接的应用程序:
java -XX:+DisableAttachMechanism cn.tuyucheng.taketoday.jmx.JMXConfiguration
之后,应用程序不会公开任何JMX/RMI端口。
此外,从JDK 16开始,我们可以设置本地端口号:
java
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.local.port=1235
cn.tuyucheng.taketoday.jmx.JMXConfiguration
现在让我们更改配置并使用远程端口。
还有一个附加选项-Dcom.sun.management.jmxremote.rmi.port=1234允许我们将RMI端口设置为与JMX端口相同的值。现在,完整的命令是:
java
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=1234
-Dcom.sun.management.jmxremote.rmi.port=1234
-Dcom.sun.management.jmxremote.local.port=1235
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
cn.tuyucheng.taketoday.jmx.JMXConfiguration
之后,netstat命令返回:
Proto Local Address Foreign Address State PID
TCP 0.0.0.0:1234 wujek:0 LISTENING 19504
TCP 0.0.0.0:1235 wujek:0 LISTENING 19504
也就是说,应用程序只暴露两个端口,一个用于JMX/RMI远程连接,一个用于本地连接。得益于此,我们可以完全控制暴露的端口,避免与其他进程暴露的端口发生冲突。
但是,当我们启用远程连接并禁用附加机制时:
java
-XX:+DisableAttachMechanism
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=1234
-Dcom.sun.management.jmxremote.rmi.port=1234
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
cn.tuyucheng.taketoday.jmx.JMXConfiguration
然后,应用程序仍然暴露两个端口:
Proto Local Address Foreign Address State PID
TCP 0.0.0.0:1234 wujek:0 LISTENING 9856
TCP 0.0.0.0:60565 wujek:0 LISTENING 9856
6. 总结
在这篇简短的文章中,我们解释了如何在Java中启动JMX。然后,我们展示了JMX在启动时打开了哪些端口。最后,我们介绍了如何限制JMX打开的端口数。
与往常一样,本教程的完整源代码可在GitHub上获得。