我的具体问题与JDK 1.6中使用的JMX有关:如果我使用JRE 1.6运行Java进程
com.sun.management.jmxremote
在命令行中,Java是否为远程JMX连接选择了一个默认端口?
背景故事:我目前正在尝试开发一个程序,让客户能够通过JMX从远程机器连接到我们的一个进程。目标是实现对实时显示控制台上发生的情况的远程调试。由于他们的服务级别协议,他们强烈要求尽可能多地捕获数据,如果情况看起来太复杂而无法快速修复,请重新启动显示控制台并允许它重新连接到服务器端。
我知道我可以在JDK 1.6进程上运行jconsole,在JDK 1.6.7进程上运行,jvisualvm给予对控制台的物理访问权限。但是,由于操作要求和涉及的人员问题,我们强烈要求远程获取我们需要的数据并重新启动并运行。
编辑:我知道命令行端口属性
com.sun.management.jmxremote.port=portNum
我想回答的问题是,如果你没有在命令行设置该属性,Java会选择另一个端口进行远程监控吗?如果是这样,你怎么能确定它可能是什么?
答案 0 :(得分:87)
答案 1 :(得分:38)
documentation表明JMX代理使用本地端口 - 无法从计算机外部访问 - 除非您指定以下属性:
com.sun.management.jmxremote.port=portNum
这是出于安全原因,以及Potato Head先生给出的理由。因此,看起来Java 6没有为JMX打开默认的可远程访问的端口。
编辑:在OP添加了更多信息的答案后添加。
您拥有的另一个选择是以某种方式创建一个本地代理,该代理侦听所有本地JMX连接并导出此信息。这样,您就不需要在服务器上对每个JVM实例进行这种神奇的配置。相反,本地代理可以通过JMX连接到所有JVM,然后以某种方式远程公开此信息。我并不确切地知道如何实现这一点,但是这样的事情可能比通过JMX远程公开所有JVM所做的工作要少。
答案 2 :(得分:6)
实际上有一个未记录的属性可用于强制JMX在随机端口号上创建远程可访问的连接器。
-Dcom.sun.management.jmxremote.authenticate="false"
-Dcom.sun.management.jmxremote="true"
-Dcom.sun.management.jmxremote.ssl="false"
-Dcom.sun.management.jmxremote.port="0"
-Dcom.sun.management.jmxremote.local.only="false"
最后两个属性是最重要的。
答案 3 :(得分:3)
documentation似乎表明JMX代理使用本地短暂端口,除非指定以下属性:
com.sun.management.jmxremote.port=portNum
可以避免使用默认端口,因为您可以在一个系统上拥有许多 java应用程序,如果有默认端口,则只能管理一个应用程序!上述配置属性是为远程管理的明确目的提供的。
如果您必须坚持使用临时端口,那么JMX代理的URL应该可以通过以下系统属性从JVM内部访问(尽管这可能是本地地址):
com.sun.management.jmxremote.localConnectorAddress
注意:我想你总是可以在远程可用的地址上打开一个套接字并将代理请求发送到本地套接字,但使用可用选项似乎更有吸引力!
答案 4 :(得分:2)
所以,对我的问题的简短回答是“不。”
但是,检查原因很有意思。查看有效本地连接的netstat
输出。以下是我看到由于jconsole
与自身建立本地连接而打开的端口。如您所见,端口1650是用于JMX信息的本地端口:
Proto Local Address Foreign Address State
TCP Gandalf:1650 Gandalf:1652 ESTABLISHED
TCP Gandalf:1650 Gandalf:1653 ESTABLISHED
TCP Gandalf:1650 Gandalf:1654 ESTABLISHED
TCP Gandalf:1650 Gandalf:1655 ESTABLISHED
TCP Gandalf:1650 Gandalf:1656 ESTABLISHED
TCP Gandalf:1652 Gandalf:1650 ESTABLISHED
TCP Gandalf:1653 Gandalf:1650 ESTABLISHED
TCP Gandalf:1654 Gandalf:1650 ESTABLISHED
TCP Gandalf:1655 Gandalf:1650 ESTABLISHED
TCP Gandalf:1656 Gandalf:1650 ESTABLISHED
但是,尝试将jconsole
连接到localhost:1650
是不够的。可悲的是,所有能够解决你问题的是“连接失败:表中没有这样的对象”消息。
因此,我原来故事的结论是,如果我们要为客户使用JMX进行远程监控,我们确实需要为在我们的系统中启动的各种Java进程确定独特的单独远程访问端口。幸运的是,所有这些都需要明智地使用VM参数:
com.sun.management.jmxremote.port=portNum
我们几乎肯定会有一个预先指定的顺序范围portNum
,以便客户可以使用端口号选择正确的远程应用程序。
答案 5 :(得分:2)
我最近一直在努力弄清楚如何从java代码启用远程JMX管理,而不需要使用特殊属性集启动JVM。我解决的解决方案是启动我自己的私有RMI注册表 - 很简单 - 并在该注册表上公开JMX服务。我创建自己的MBeanServer,然后创建一个新的JMXConnectorServer。 JMXConnectorServer是通过类似
的调用创建的connector = JXMConnectorServerFactory.newJMXConnectorServer(url, null, server);
其中server是MBeanServer,url是JMXServiceURL的实例。
url的格式为“service:jmx:rmi:/// jndi / rmi:// localhost:/ jmxrmi”,其中port是(本地)私有注册表的端口号。 “jmxrmi”是JMX服务的标准服务名称。
设置完成后,启动连接器后,我发现可以使用hostname:port从jconsole连接到它。
这完全符合我的需要;我很想知道是否有人看到这种方法存在缺陷。
答案 6 :(得分:0)
如果您碰巧在Glassfish应用服务器中运行应用程序,只需运行以下asadmin命令,您需要重新启动所有正在运行的服务器才能使更改生效。
./ asadmin enable-secure-admin
还有额外的Glassfish服务器配置可以进一步提高安全性,详见Connecting remotely to Glassfish through JMX。