简体   繁体   English

发现 Java 的 JMX 临时端口号 9+

[英]Discovering JMX Ephemeral Port Number for Java 9+

This question: When using a JMX server with ephemeral port, how to get the server port number?这个问题: 当使用带有临时端口的JMX服务器时,如何获取服务器端口号? indicates that we can use sun.management.ConnectorAddressLink with the params specified to discover the ephemeral JMX port (if we start our process with com.sun.management.jmxremote.port=0 ).表示我们可以使用带有指定参数的sun.management.ConnectorAddressLink来发现临时 JMX 端口(如果我们使用com.sun.management.jmxremote.port=0开始我们的进程)。

However for Java 9+, these classes were made private and can no longer be accessed.但是,对于 Java 9+,这些类已设为私有,无法再访问。 Is there any way one could programmatically find which port JMX has bound to?有什么方法可以通过编程方式找到 JMX 绑定到的端口?

ConnectorAddressLink class can be invoked via jdk.internal.agent module. ConnectorAddressLink class 可以通过 jdk.internal.agent 模块调用。

Below sample code shows how we can programmatically find JMX ephemeral port in java 9/11/14 (Tested with OpenJDK versions only).下面的示例代码显示了我们如何以编程方式在 java 9/11/14 中找到 JMX 临时端口(仅使用 OpenJDK 版本测试)。

Java 9+ Code: Java 9+ 代码:

In the below code you can get PID or use 0 to denote current PID hence providing a way to show JMX URL in both scenarios and they will be identical.在下面的代码中,您可以获得 PID 或使用 0 表示当前 PID,因此提供了一种在两种情况下显示 JMX URL 的方法,它们将是相同的。

public class JMXEphemeralPortTest_JAVA9Plus {

  public static void main(String[] args) throws IOException {
    String jmxURL = "NO JMX URL";
    String jmxURL2 = "NO JMX URL";
    if (isJava9Plus(System.getProperties())) {
      long pid = ProcessHandle.current().pid();
      jmxURL = "From Java 9 Plus:-->" + importRemoteFrom_Java9Plus(Math.toIntExact(pid));
      jmxURL2 = "From Java 9 Plus:-->" + importRemoteFrom_Java9Plus(0);
    }
    System.out.println(jmxURL);
    System.out.println(jmxURL2);
  }
  private static boolean isJava9Plus(Properties properties) {
    double javaVersion = Double.parseDouble(properties.getProperty("java.specification.version"));
    System.out.println("Java Version:"+javaVersion);
    return javaVersion >= 1.9;
  }
  private static String importRemoteFrom_Java9Plus(int pid) {
    try {
      final Class<?> clazz = Class.forName("jdk.internal.agent.ConnectorAddressLink");
      final Method method = clazz.getMethod("importRemoteFrom", int.class);
      final Object instance = clazz.getDeclaredConstructor().newInstance();
      Map<String, String> map = (Map<String, String>) method.invoke(instance, pid);
      return map.get("sun.management.JMXConnectorServer.0.remoteAddress");
    } catch (Exception e) {
      throw new IllegalStateException("Could not load needed java 9+ class", e);
    }
  }
}

* Java 9+ VM Arguments for the module and JMX : * Java 9+ VM Arguments 用于模块和 JMX

--add-modules jdk.management,jdk.management.agent
--add-exports=jdk.management.agent/jdk.internal.agent=ALL-UNNAMED
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=0
-Dcom.sun.management.jmxremote.local.only=false

Java 9+ Result: Java 9+ 结果:

Java Version:14.0 From Java 9 Plus:-->service:jmx:rmi:///jndi/rmi://XXXX:50678/jmxrmi From Java 9 Plus:-->service:jmx:rmi:///jndi/rmi://XXXX:50678/jmxrmi Java Version:14.0 From Java 9 Plus:-->service:jmx:rmi:///jndi/rmi://XXXX:50678/jmxrmi From Java 9 Plus:-->service:jmx:rmi:///jndi /rmi://XXXX:50678/jmxrmi

Java Version:9.0 From Java 9 Plus:-->service:jmx:rmi:///jndi/rmi://XXXX:60342/jmxrmi From Java 9 Plus:-->service:jmx:rmi:///jndi/rmi://XXXX:60342/jmxrmi Java Version:9.0 From Java 9 Plus:-->service:jmx:rmi:///jndi/rmi://XXXX:60342/jmxrmi From Java 9 Plus:-->service:jmx:rmi:///jndi /rmi://XXXX:60342/jmxrmi

Happy programming.快乐编程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM