Java 6 是否为 JMX 远程连接打开默认端口?

发布于 2024-07-13 01:25:23 字数 820 浏览 14 评论 0 原文

我的具体问题与 JDK 1.6 中使用的 JMX 有关:如果我

com.sun.management.jmxremote

在命令行中使用 JRE 1.6 运行 Java 进程,Java 是否会为远程 JMX 连接选择默认端口?

背景故事:我目前正在尝试开发一个程序提供给客户,使他们能够通过 JMX 从远程计算机连接到我们的一个进程。 目标是促进他们对实时显示控制台上发生的情况进行远程调试。 由于他们的服务级别协议,他们强烈希望捕获尽可能多的数据,并且如果情况看起来太复杂而无法快速修复,则重新启动显示控制台并允许其重新连接到服务器端。

我知道我可以在 JDK 1.6 进程上运行 jconsolejvisualvm 在给定物理的 JDK 1.6.7 后进程上访问控制台。 然而,由于涉及的操作要求和人员问题,我们强烈希望远程获取所需的数据并使其重新启动和运行。

编辑:我知道命令行端口属性

com.sun.management.jmxremote.port=portNum

我想回答的问题是,如果您不在命令行中设置该属性,Java 是否会选择另一个端口进行远程监控? 如果是这样,您如何确定它可能是什么?

My specific question has to do with JMX as used in JDK 1.6: if I am running a Java process using JRE 1.6 with

com.sun.management.jmxremote

in the command line, does Java pick a default port for remote JMX connections?

Backstory: I am currently trying to develop a procedure to give to a customer that will enable them to connect to one of our processes via JMX from a remote machine. The goal is to facillitate their remote debugging of a situation occurring on a real-time display console. Because of their service level agreement, they are strongly motivated to capture as much data as possible and, if the situation looks too complicated to fix quickly, to restart the display console and allow it to reconnect to the server-side.

I am aware the I could run jconsole on JDK 1.6 processes and jvisualvm on post-JDK 1.6.7 processes given physical access to the console. However, because of the operational requirements and people problems involved, we are strongly motivated to grab the data that we need remotely and get them up and running again.

EDIT: I am aware of the command line port property

com.sun.management.jmxremote.port=portNum

The question that I am trying to answer is, if you do not set that property at the command line, does Java pick another port for remote monitoring? If so, how could you determine what it might be?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

楠木可依 2024-07-20 01:25:23

据我所知,

以下是连接JMX客户端进程的可能性(管理应用程序,如 jconsole、jmxterm、mc4j、jvmstat、jmxmonitor、jps、 ...)到JMX服务器进程代理)。

连接 JMX 客户端和 JMX 服务器的协议假定为“Java RMI”(又名“RMI-JRMP”)。 这应该是默认值。 可以配置其他协议 ,特别是“RMI-IIOP”和“JMXMP”。 特殊协议是可能的:例如 MX4J 项目还提供 SOAP/HTTP 和基于 HTTP 的各种序列化协议。

有关详细信息,请参阅 Sun/Oracle 文档配置。

另请查看 JDK 发行版中的文件 jre/lib/management/management.properties

因此,可能的情况是:

情况 0:JVM 在没有任何特定配置的情况下启动

在 Java 6 之前:JVM 不充当 JMX 服务器。 在 JVM 内运行的任何程序都可以访问 JVM 的 MBeanServer 以编程方式使用它在线程之间进行有趣的数据交换或进行 JVM 监视,但无法从 JVM 进程外部进行管理。

从 Java 6 开始:即使没有明确配置,也可以在本地(从同一台计算机)访问 JVM 的 JMX 功能,如“案例 1”中所述。

情况 1:JVM 使用 -Dcom.sun.management.jmxremote 启动

JVM 配置为本地(同一台机器) -仅)JMX 服务器。

在这种情况下(原则上仅适用于 Sun/Oracle JVM),JMX 客户端可以通过 /tmp/hsperfdata_[user] 中找到的内存映射文件连接到 JMX 服务器。 Sun 文档中提到了这一点,称为“本地监控”(以及 附加 API)。 它不适用于 FAT 文件系统,因为无法正确设置权限。 请参阅此博客文章

Sun 建议在与 JMX 服务器分开的计算机上运行 jconsole,因为 jconsole 显然是一个资源消耗者,因此这种“本地监视”不一定是一个好主意。

然而,本地监控相当安全,只能在本地使用,并且可以通过文件系统权限轻松控制。

情况 2:JMX 服务器通过 -Dcom.sun.management.jmxremote.port=[rmiregistryport] 启动

JVM 配置为作为 JMX 服务器侦听多个端口TCP 端口。

命令行上指定的端口将由 JVM 分配,并且 RMI 注册表将在那里可用。 注册表公布了一个名为“jmxrmi”的连接器。 它指向第二个随机分配的 TCP 端口(“临时”端口),JMX RMI 服务器在该端口上侦听并通过该端口进行实际数据交换。

“情况 1”中描述的本地在“情况 2”中始终启用。

JMX 服务器默认侦听所有接口,因此您可以通过本地连接到 127.0.0.1:[rmiregistryport] 以及远程连接到 [任何外部 IP 地址]:[某个端口] 来连接到它(并控制它) 。

这意味着您必须考虑安全隐患。 您只需设置 -Dcom.sun.management.jmxremote.local.only=true 即可让 JVM 监听 127.0.0.1:[rmiregistryport]。

不幸的是,我们无法指定临时端口将分配到哪里——它总是在启动时随机选择的。 这很可能意味着您的防火墙需要成为该死的瑞士奶酪! 不过,有解决方法。 特别是,Apache Tomcat 通过其 JMX 设置临时 JMX RMI 服务器端口远程生命周期监听器。 执行这个小魔法的代码可以在 org.apache.catalina.mbeans.JmxRemoteLifecycleListener

如果您使用此方法,您不妨确保:

  1. JMX 客户端必须向 JMX 服务器进行身份验证
  2. 客户端和服务器之间的 TCP 交换使用 SSL 进行加密

如何完成此操作,请参阅 Sun/Oracle 文档

其他方法

您可以进行有趣的排列以避免使用 RMI 协议。 特别是,您可以将 servlet 引擎(如 Jetty)添加到您的流程中。 然后添加 servlet,将一些基于 HTTP 的交换内部转换为对 JVM 的 MBeanServer 的直接访问。 然后,您将处于“情况 0”,但仍然具有管理功能(可能通过基于 HTML 的界面)。 JBoss JMX Console 就是一个示例。

更离题的是,您可以根据本文档

显示并告知时间

现在是时候用一些代码来说明 JXM 交换了。 我们从Sunoracle 教程中获得灵感。

它在 Unix 上运行。 我们使用配置为 JMX 服务器的 JVM,使用:

-Dcom.sun.management.jmxremote.port=9001

我们使用 lsof 来检查它持有哪些 TCP 端口打开:

lsof -p -n | grep TCP

人们应该看到类似这样的东西,注册端口和临时端口:

java    1068 user  127u  IPv6 125614246                 TCP *:36828 (LISTEN)
java    1068 user  130u  IPv6 125614248                 TCP *:9001  (LISTEN)

我们使用 tcpdump 来检查 JMX 客户端和 JMX 服务器之间的数据包交换:

tcpdump -l - XX 端口 36828 或端口 9001

我们在主目录中设置一个文件 .java.policy 以允许客户端实际进行远程连接:

grant {
    permission java.net.SocketPermission 
    "<JMX server IP address>:1024-65535", "connect,resolve";
};

然后我们可以运行它并看看会发生什么:

package rmi;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import javax.management.remote.rmi.RMIConnection;
import javax.management.remote.rmi.RMIServer;

public class Rmi {

    public static void main(String args[]) throws Exception {
        // We need a Security Manager (not necessarily an RMISecurityManager)
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
        //
        // Define a registry (this is just about building a local data structure)
        // 
        final int comSunManagementJmxRemotePort = 9001;
        Registry registry = LocateRegistry.getRegistry("<JMX server IP address>", comSunManagementJmxRemotePort);
        //
        // List registry entries. The client connects (using TCP) to the server on the
        // 'com.sun.management.jmxremote.port' and queries data to fill the local registry structure.
        // Among others, a definition for 'jmxrmi' is obtained.
        //
        System.out.print("Press enter to list registry entries");
        System.in.read();
        String[] names = registry.list();
        for (String name : names) {
            System.out.println("In the registry: " + name);
        }
        //
        // 'Looking up' the entry registered under 'jmxrmi' involves opening and tearing down
        // a TCP connection to the 'com.sun.management.jmxremote.port', as well as a TCP
        // connection to an ephemeral secondary port chosen at server startup.
        // The actual object locally obtained is a "javax.management.remote.rmi.RMIServerImpl_Stub"
        // indicating where the ephemeral port is.
        // "RMIServerImpl_Stub[UnicastRef [liveRef: [endpoint:[$IP:$EPHEMERAL_PORT](remote),objID:[-62fb4c1c:131a8c709f4:-7fff, -3335792051140327600]]]]"        
        //
        System.out.print("Press enter to get the 'jmxrmi' stub");
        System.in.read();
        RMIServer jmxrmiServer = (RMIServer)registry.lookup("jmxrmi");
        System.out.println(jmxrmiServer.toString());
        //
        // Now get a "RMI Connection" to the remote. This involves setting up and tearing
        // down a TCP connection to the ephemeral port. 
        //        
        System.out.print("Press enter to get the 'RMIConnection'");
        System.in.read();
        RMIConnection rcon = jmxrmiServer.newClient(null);
        //
        // Ask away. This involves setting up and tearing
        // down a TCP connection to the ephemeral port. 
        //
        System.out.print("Press enter to get the 'domains'");
        System.in.read();
        for (String domain : rcon.getDomains(null)) {
            System.out.println("Domain: " + domain);
        }
        //
        // Ok, that will do. For serious applications, we better use the higher-level JMX classes
        //
    }   
}

AFAIK,

Here are the possibilites for connecting a JMX client process (a management application like jconsole, jmxterm, mc4j, jvmstat, jmxmonitor, jps, ...) to a JMX server process (the agent).

The protocol connecting JMX client and JMX server is assumed to be 'Java RMI' (aka 'RMI-JRMP'). This should be the default. One can configure other protocols, in particular 'RMI-IIOP' and 'JMXMP'. Special protocols are possible: the MX4J project for example additionally provides SOAP/HTTP and various serialization protocols over HTTP.

Refer to Sun/Oracle docs for details on configuration.

Also have a look at the file jre/lib/management/management.properties in your JDK distribution.

So, the possibilities:

Case 0: The JVM is started without any particular configuration

Before Java 6: The JVM does not behave as a JMX server. Any program that is run inside the JVM may access the JVM's MBeanServer programmatically and use it to do interesting data exchanges between threads or to do JVM monitoring, but no management from outside the JVM process is possible.

Since Java 6: Even if not explicitely configured, one can access JMX functionality of the JVM locally (from the same machine) as described in "Case 1".

Case 1: The JVM is started with -Dcom.sun.management.jmxremote

The JVM is configured to work as a local (same-machine-only) JMX server.

In this case (and in principle only for Sun/Oracle JVMs) a JMX client can connect to the JMX server through memory-mapped files found in /tmp/hsperfdata_[user]. This is alluded to in the Sun documentation and called "local monitoring" (and also the Attach API). It does not work on FAT filesystems as permissions cannot be set correctly there. See this blog entry.

Sun recommends running jconsole on a machine separate from the JMX server as jconsole apparently is a resource hog, so this "local monitoring" thing is not necessarily a good idea.

Local monitoring is, however, rather secure, only being usable locally and being easily controlled through filesystem permissions.

Case 2: The JMX server is started with -Dcom.sun.management.jmxremote.port=[rmiregistryport]

The JVM is configured to work as a JMX server listening on several TCP ports.

The port specified on the command line will be allocated by the JVM and an RMI registry will be available there. The registry advertises a connector named 'jmxrmi'. It points to a second, randomly allocated TCP port (an 'ephemeral' port) on which the JMX RMI server listens and through which actual data exchange takes place.

Local as described in 'Case 1' is always enabled in 'Case 2'.

The JMX server listens on all interfaces by default, so you can connect to it (and control it) by locally connecting to 127.0.0.1:[rmiregistryport] as well by remotely connecting to [any outside IP address]:[some port] remotely.

This implies that you have to look at the security implications. You can make the JVM listen on 127.0.0.1:[rmiregistryport] only by setting -Dcom.sun.management.jmxremote.local.only=true.

It is rather unfortunate that one cannot specify where the ephemeral port will be allocated - it is always chosen randomly at startup. This may well mean that your firewall needs to become the swiss cheese of the damned! However, there are workarounds. In particular, Apache Tomcat sets the ephemeral JMX RMI server port via its JMX Remote Lifecycle Listener. The code to perform this little magic can be found at org.apache.catalina.mbeans.JmxRemoteLifecycleListener.

If you use this method, you might as well make sure that:

  1. The JMX client has to authenticate to the JMX server
  2. The TCP exchange between the client and server is encrypted using SSL

How that is done is described in the Sun/Oracle documentation

Other approaches

You can do interesting permutations to avoid having to use the RMI protocol. In particular, you could add a servlet engine (like Jetty) to your process. Then add servlets that translate some HTTP-based exchange internally into direct accesses to the JVM's MBeanServer. You would then be in 'case 0' but still have management capabilities, possibly through an HTML-based interface. The JBoss JMX Console is an example of this.

More off-topic, you could use SNMP directly (something I haven't tried) according to this document.

Show and Tell Time

And now it's time for some code to illustrate a JXM exchange. We take inspiration from a Sunoracle tutorial.

This runs on Unix. We use a JVM that is configured as a JMX server using:

-Dcom.sun.management.jmxremote.port=9001

We use lsof to check what TCP ports it is holding open:

lsof -p <processid> -n | grep TCP

One should see something like this, the registry port and the ephemeral port:

java    1068 user  127u  IPv6 125614246                 TCP *:36828 (LISTEN)
java    1068 user  130u  IPv6 125614248                 TCP *:9001  (LISTEN)

We use tcpdump to inspect the packet exchange between JMX client and JMX server:

tcpdump -l -XX port 36828 or port 9001

We set up a file .java.policy in the home directory to allow the client to actually connect remotely:

grant {
    permission java.net.SocketPermission 
    "<JMX server IP address>:1024-65535", "connect,resolve";
};

And then we can run this and see what happens:

package rmi;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import javax.management.remote.rmi.RMIConnection;
import javax.management.remote.rmi.RMIServer;

public class Rmi {

    public static void main(String args[]) throws Exception {
        // We need a Security Manager (not necessarily an RMISecurityManager)
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
        //
        // Define a registry (this is just about building a local data structure)
        // 
        final int comSunManagementJmxRemotePort = 9001;
        Registry registry = LocateRegistry.getRegistry("<JMX server IP address>", comSunManagementJmxRemotePort);
        //
        // List registry entries. The client connects (using TCP) to the server on the
        // 'com.sun.management.jmxremote.port' and queries data to fill the local registry structure.
        // Among others, a definition for 'jmxrmi' is obtained.
        //
        System.out.print("Press enter to list registry entries");
        System.in.read();
        String[] names = registry.list();
        for (String name : names) {
            System.out.println("In the registry: " + name);
        }
        //
        // 'Looking up' the entry registered under 'jmxrmi' involves opening and tearing down
        // a TCP connection to the 'com.sun.management.jmxremote.port', as well as a TCP
        // connection to an ephemeral secondary port chosen at server startup.
        // The actual object locally obtained is a "javax.management.remote.rmi.RMIServerImpl_Stub"
        // indicating where the ephemeral port is.
        // "RMIServerImpl_Stub[UnicastRef [liveRef: [endpoint:[$IP:$EPHEMERAL_PORT](remote),objID:[-62fb4c1c:131a8c709f4:-7fff, -3335792051140327600]]]]"        
        //
        System.out.print("Press enter to get the 'jmxrmi' stub");
        System.in.read();
        RMIServer jmxrmiServer = (RMIServer)registry.lookup("jmxrmi");
        System.out.println(jmxrmiServer.toString());
        //
        // Now get a "RMI Connection" to the remote. This involves setting up and tearing
        // down a TCP connection to the ephemeral port. 
        //        
        System.out.print("Press enter to get the 'RMIConnection'");
        System.in.read();
        RMIConnection rcon = jmxrmiServer.newClient(null);
        //
        // Ask away. This involves setting up and tearing
        // down a TCP connection to the ephemeral port. 
        //
        System.out.print("Press enter to get the 'domains'");
        System.in.read();
        for (String domain : rcon.getDomains(null)) {
            System.out.println("Domain: " + domain);
        }
        //
        // Ok, that will do. For serious applications, we better use the higher-level JMX classes
        //
    }   
}
愁杀 2024-07-20 01:25:23

文档建议 JMX 代理使用本地端口——从机器外部无法访问的端口——除非您指定以下属性:

com.sun.management.jmxremote.port=portNum

这是出于安全原因,以及土豆头先生给出的理由。 因此,Java 6 似乎没有为 JMX 打开默认的远程访问端口。

编辑:在 OP 添加包含更多信息的答案后添加。

您的另一个选择是以某种方式创建一个本地代理来侦听所有本地 JMX 连接并导出此信息。 这样,您就不需要对服务器上的每个 JVM 实例进行如此神奇的配置。 相反,本地代理可以通过 JMX 连接到所有 JVM,然后以某种方式远程公开此信息。 我不确定您将如何实现这一点,但是与通过 JMX 远程公开所有 JVM 所需要做的工作相比,这样的事情可能会更少。

The documentation suggests that the JMX agent uses a local port -- something unreachable from outside the machine -- unless you specify the following property:

com.sun.management.jmxremote.port=portNum

This is for security reasons, as well as for the reason given by Mr Potato Head. Thus, it looks like Java 6 does not open a default remotely accessible port for JMX.

EDIT: Added after the OP added an answer with more information.

Another option you have is to somehow create a local proxy that listens to all local JMX connections and exports this information. This way, you don't need to have such magic configuration of each JVM instance on the server. Instead the local proxy can connect to all JVMs via JMX and then somehow expose this information remotely. I am not positive exactly how you would implement this, but something like this may be less work than what you otherwise have to do to expose all of your JVMs remotely via JMX.

时光是把杀猪刀 2024-07-20 01:25:23

实际上,您可以使用一个未记录的属性来强制 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"

最后两个属性是最重要的。

Actually there is an undocumented property that you can use to force JMX create remotely accessible connectors on random port numbers.

-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"

Last two properties are of most importance.

薯片软お妹 2024-07-20 01:25:23

文档似乎表明 JMX代理使用本地临时端口,除非指定以下属性:

com.sun.management.jmxremote.port=portNum

避免使用默认端口,因为一个系统上可能有许多个java应用程序,并且如果有默认端口,只能管理一个应用程序! 上述配置属性是为了远程管理的明确目的而提供的。

如果您必须坚持使用临时端口,则应该可以通过以下系统属性从 JVM 内部访问 JMX 代理的 URL(尽管这可能是本地地址):

com.sun.management.jmxremote.localConnectorAddress

注意 :我想你总是可以在远程可用地址上打开一个套接字,并向本地套接字发出代理请求,但使用可用选项似乎更具吸引力!

The documentation seems to indicate that the JMX agent uses a local ephemeral port, unless you specify the following property:

com.sun.management.jmxremote.port=portNum

Default ports are avoided because you could have many java applications on one system, and if there was a default port, only one application would be able to be managed! The above configuration property is provided for the express purpose of remote management.

If you must insist on using an ephemeral port, then the URL of the JMX agent should be accessible from within the JVM, through the following system property (although this is likely to be a local address):

com.sun.management.jmxremote.localConnectorAddress

Note: I guess you could always open a socket on a remotely-available address and proxy requests on to the local socket, but using the available option seems far more attractive!

我的黑色迷你裙 2024-07-20 01:25:23

所以,我的问题的简短答案是“不”。

然而,研究一下原因很有趣。 查看有效本地连接的 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 范围,以便客户可以使用端口号选择正确的远程应用程序。

So, the short answer to my question is "no."

However, it's interesting to examine why. Look at the netstat output from a valid local connection. Here are the ports that I see opened up as a result of a jconsole making a local connection to itself. As you can see, port 1650 is the local port being used for the JMX information:

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

However, it's not sufficient to try to connect jconsole to localhost:1650. Sadly, all that will net you is a "Connection failed: no such object in table" message.

So, the conclusion of my original story is that, if we are going to facilitate remote monitoring using JMX for our customers, we really need to identify unique individual remote access ports for the variety of Java processes that are started in our system. Fortunately, all this requires is the judicious use of the VM argument:

com.sun.management.jmxremote.port=portNum

where we will almost certainly have a sequential pre-specified range of portNum so that the customer can select the correct remote application using the port number.

入怼 2024-07-20 01:25:23

我最近一直在研究如何从 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 服务的标准服务名称。

设置完毕并启动连接器后,我发现可以使用主机名:端口从 jconsole 连接到它。

这完全满足了我的需求; 我很想知道是否有人发现这种方法的缺陷。

参考:JMX 教程,第 1 章 3

I've been working recently to figure out how to enable remote JMX management from java code, without requiring the JVM to have been started with special properties set. The solution I settled on is to start my own private RMI registry -- easy enough -- and to expose the JMX service on that registry. I create my own MBeanServer, then create a new JMXConnectorServer. The JMXConnectorServer is created through a call like

connector = JXMConnectorServerFactory.newJMXConnectorServer(url, null, server);

Where server is the MBeanServer, and url is an instance of JMXServiceURL.

The url is of the form "service:jmx:rmi:///jndi/rmi://localhost:/jmxrmi" where port is the (local) private registry's port number. "jmxrmi" is the standard service name for the JMX service.

After setting this up, and starting the connector, I find that I can connect to it from jconsole using hostname:port.

This entirely addresses my needs; I will be interested to know if anyone sees a flaw in this approach.

Reference: JMX Tutorial, Chap. 3

白日梦 2024-07-20 01:25:23

如果您碰巧在 Glassfish 应用程序服务器内运行应用程序,只需运行以下 asadmin 命令,您将需要重新启动所有正在运行的服务器才能使更改生效。

./asadmin enable-secure-admin

还有额外的 Glassfish 服务器配置可以进一步启用安全性,请参阅 连接通过 JMX 远程连接到 Glassfish

If you happen to run your application inside Glassfish app server, simply run the following asadmin command, you would need to restart all running servers for the change to take affect.

./asadmin enable-secure-admin

There are extra Glassfish server configurations to further enable security, see more at Connecting remotely to Glassfish through JMX.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文