如何在我的JVM上激活JMX以便使用jconsole进行访问?

255

如何在JVM上激活JMX以便使用jconsole访问?


33
允许这样做,实际上这只是提醒我自己的方式,因为我总是忘记从哪里复制参数,现在我知道在哪里找到它了 :-) - Mauli
21
Stack Exchange一直在明确鼓励用户回答自己的问题,详见:http://stackoverflow.com/help/self-answer。 - Tim Büthe
11
有时我在 Stack Overflow 上搜索某些内容,发现一个问题的答案……是我自己回答的。其中之一也是我自己提出的。这就是为什么将你自己的答案放进去是很好的。此外,想想所有可能遇到同样问题的其他人,如果您回答了自己的问题,也将帮助他们。 - Mike Miller
2
Java 8的更新文档在这里 - Andrew Johnston
@Mauren:你能提供一下你自己回答的那个已关闭问题的参考吗?这可能值得在 Meta 上讨论一下。 - kevinarpe
显示剩余2条评论
12个回答

330
相关文件可以在这里找到:

http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html

开始你的程序时,请使用以下参数:
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.rmi.port=9010
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

例如像这样:
java -Dcom.sun.management.jmxremote \
  -Dcom.sun.management.jmxremote.port=9010 \
  -Dcom.sun.management.jmxremote.local.only=false \
  -Dcom.sun.management.jmxremote.authenticate=false \
  -Dcom.sun.management.jmxremote.ssl=false \
  -jar Notepad.jar

-Dcom.sun.management.jmxremote.local.only=false 不是必需的,但如果没有它,在Ubuntu上将无法正常工作。错误信息可能类似于:

01 Oct 2008 2:16:22 PM sun.rmi.transport. customer .TCPTransport$AcceptLoop executeAcceptLoop
WARNING: RMI TCP Accept-0: accept loop for ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=37278] throws
java.io.IOException: The server sockets created using the LocalRMIServerSocketFactory only accept connections from clients running on the host where the RMI remote objects have been exported.
    at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:89)
    at sun.rmi.transport. customer .TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:387)
    at sun.rmi.transport. customer .TCPTransport$AcceptLoop.run(TCPTransport.java:359)
    at java.lang.Thread.run(Thread.java:636)

看看https://bugs.java.com/bugdatabase/view_bug?bug_id=6754672

还要小心-Dcom.sun.management.jmxremote.authenticate=false,这使得任何人都可以访问,但如果你只是用它来跟踪本地机器上的JVM,那就没关系。

更新

在某些情况下,我无法访问服务器。如果我设置了这个参数:-Djava.rmi.server.hostname=127.0.0.1,问题就会解决。


11
现在在Centos上也需要使用-Dcom.sun.management.jmxremote.local.only=false。 - LenW
1
吹毛求疵:对我来说,com.sun.management.jmxremote 的默认值为 true 真的很奇怪。(感谢 Sun!)为了更加清晰明了,特别是对于那些不太熟悉 JMX 的人,我使用:com.sun.management.jmxremote=true 参考文献:http://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html - kevinarpe
2
"-Djava.rmi.server.hostname" 对我来说非常好用! - Orhun D.
1
如果您正在尝试通过SSH隧道连接到远程服务器,将主机名设置为localhost非常重要,这是非常常见的情况。 - Nikhil Owalekar
1
只有在服务器上禁用防火墙时才能正常工作。在这个例子中,我打开了9010/tcp端口,当然,我还尝试添加了Dcom.sun.management.jmxremote.rmi.port=9011并在防火墙中打开 - 但仍无法连接。有什么想法吗?我有遗漏什么吗? - Carmageddon
显示剩余4条评论

80
在Docker容器中运行会引入一系列额外的连接问题,希望这能帮助到某些人。我最终需要添加以下选项,下面我将解释一下:
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=${DOCKER_HOST_IP}
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.rmi.port=9998

DOCKER_HOST_IP

与在本地使用jconsole不同,您需要广告一个与容器内部看到的IP地址不同的IP地址。 您需要将${DOCKER_HOST_IP}替换为Docker主机的可外部解析IP(DNS名称)。

JMX远程和RMI端口

看起来JMX还需要访问远程管理接口(jstat),该接口使用不同的端口传输一些数据以协调连接。 我没有在jconsole中看到任何明显设置此值的地方。 在链接的文章中,步骤如下:

  • 尝试启用日志记录从jconsole连接
  • 失败
  • 找出jconsole尝试使用的端口
  • 根据需要使用iptables / firewall规则允许该端口连接

虽然那样做可以实现目的,但它肯定不是一种可自动化的解决方案。我选择从jconsole升级到VisualVM,因为它允许您明确指定jstatd正在运行的端口。在VisualVM中,添加一个新的远程主机,并使用与上述值相对应的值进行更新:

Add Remote Host

然后右键点击新的远程主机连接,选择“添加JMX连接...”

Add JMX Connection

不要忘记勾选“不需要SSL连接”的复选框。希望这样可以让你成功连接。

1
-Djava.rmi.server.hostname=localhost -Dcom.sun.management.jmxremote.rmi.port=[...] 这两个参数也是在通过SSH隧道传输JMX/RMI时的关键。如果没有这些参数,远程对象将使用服务器的公共/主要/... IP和一些随机端口进行访问,这些端口不易被转发。 - Thorsten Schöning
1
我可以确认你确实需要使用外部容器IP。例如,使用“-Djava.rmi.server.hostname=0.0.0.0”是无法正常工作的。 - raisercostin
1
我不需要在任何地方使用 DOCKER_HOST_IP - 我只是使用 localhost 并在运行 Docker 镜像时转发端口:-p 9998:9998, -p 9999:9999 等。 - Barney
这对我的Docker-Java-Setup也起作用。更容易提到jstatd端口等同于-Dcom.sun.management.jmxremote.rmi.port参数。虽然没有明确说明,但这会提高您的答案质量。谢谢! - Webchen

10
注意,最新版本的Java 6允许jconsole在未经过JMX语言启动的情况下附加到正在运行的进程。 如果您能使用该功能,还请考虑使用jvisualvm它可以提供有关运行进程的大量信息,包括分析器。

5
只有在您运行jconsole的主机上监视JVM时才有效。 - Gray
1
@ Thorbjorn 如果我在没有任何参数的情况下启动我的Java程序并尝试使用jconsole连接,我可以在程序列表中看到它,但是当我尝试连接时失败了。我认为这是由于缺乏SSL证书造成的。我只想看一下演示,因此我不得不使用用户3013578指定的参数,这对我有用(JDK 1.7,Windows 8.1,64位)。 - Captain_spack_jarrow
2
附加API在某些平台上要求jconsole与启动程序具有相同的32/64位JVM。 - Thorbjørn Ravn Andersen
1
这个行为可以被禁用吗? - kevinarpe

7
我是使用WAS ND 7.0的。
我的JVM需要所有以下参数在JConsole中被监控。
    -Djavax.management.builder.initial= 
    -Dcom.sun.management.jmxremote 
    -Dcom.sun.management.jmxremote.port=8855 
    -Dcom.sun.management.jmxremote.authenticate=false 
    -Dcom.sun.management.jmxremote.ssl=false

是的,你的答案对我有用(JDK 1.7,Windows 8.1 64位)。 - Captain_spack_jarrow

6

在Linux上,我使用了以下参数:

-Djavax.management.builder.initial= 
-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=9010 
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false

而且我修改了/etc/hosts文件,以使主机名解析为主机地址(192.168.0.x),而不是环回地址(127.0.0.1)


4
以下选项适合我:
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.rmi.port=9010
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname={host name}

记得在服务器上打开9010端口

sudo ufw allow 9010/udp
sudo ufw allow 9010/tcp
sudo ufw reload

4

除了以下命令行参数之外,

-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

有时在Linux服务器上,IMX连接无法成功。这是因为在Cloud Linux主机中,在/etc/hosts文件中未将主机名解析为主机地址。
修复此问题的最佳方法是从网络中的其他计算机ping特定的Linux服务器并使用该主机IP地址。请确保在/etc/hosts文件中添加正确的解析信息。
-Djava.rmi.server.hostname=IP address that obtained when you ping that linux server.

但是不要依赖使用ifconfig.me从Linux服务器获取的ip地址。您在那里获得的IP是掩码的,存在于主机文件中。


2

使用远程进程选项运行本地JCONSOLE

要在本地运行,请按照以下步骤操作:

我在我的vm参数中添加了以下内容:

-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=6001
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=localhost
-Dcom.sun.management.jmxremote.rmi.port=6001

我通过Intellij终端打开了JConsole,它在本地以灰色显示所有PID。因此,我选择了远程进程并使用主机localhost:6001登录。保持用户名和密码为空,然后点击连接。
请确保没有其他进程在端口6001上运行。您也可以使用其他端口。

2

使用以下命令行参数运行您的Java应用程序:

-Dcom.sun.management.jmxremote.port=8855
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false

如果您不想在jmx主机上设置数字证书,那么使用-Dcom.sun.management.jmxremote.ssl=false参数非常重要。

如果您在IP地址为192.168.0.1的计算机上启动了应用程序,请打开jconsole,在远程进程字段中输入192.168.0.1:8855,然后单击连接


如果忘记添加“-Dcom.sun.management.jmxremote.ssl=false”,预期的行为是什么?jconsole会显示错误,还是只是静默地无法连接? - amacleod

2

步骤1: 使用以下参数运行应用程序。

-Dcom.sun.management.jmxremote.port=9999 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false

以上参数将应用程序绑定到端口9999。

步骤2:通过在命令提示符或终端中执行jconsole命令来启动jconsole。

选择“远程进程:”,并将url输入为{IP_Address}:9999,然后单击“连接”按钮以连接到远程应用程序。

您可以参考此链接获取完整的应用程序。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接