1. 概述
在这个教程中,我们将解释为什么JMX在启动时会打开三个端口。此外,我们将演示如何在Java中启动JMX,并展示如何限制打开的端口号。
2. JMX定义
首先,让我们定义一下JMX框架。Java管理扩展(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 com.baeldung.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暴露应用程序。换句话说,它自动通过Local Process为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
为了远程连接,我们必须提供端口号作为必选参数。我们禁用认证和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 com.baeldung.jmx.JMXConfiguration
这样,应用程序就不暴露任何JMX/RMI端口了。
此外,从JDK 16开始,我们可以设置本地端口号:
java
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.local.port=1235
com.baeldung.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
com.baeldung.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
这意味着应用程序只暴露两个端口:一个用于RMI/JMX的远程连接,另一个用于本地连接。这样,我们可以完全控制暴露的端口,避免与其他进程暴露的端口冲突。
但是,当启用远程连接并禁用attach机制时:
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
com.baeldung.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上找到。