发现 Java 9+ 的 JMX 临时端口号
Discovering JMX Ephemeral Port Number for Java 9+
这个问题: 表示我们可以使用 sun.management.ConnectorAddressLink
和指定的参数来发现临时 JMX 端口(如果我们使用 com.sun.management.jmxremote.port=0
启动进程)。
但是对于 Java 9+,这些 类 被设为私有并且无法再访问。有什么方法可以通过编程找到 JMX 绑定到哪个端口?
ConnectorAddressLink class 可以通过 jdk.internal.agent 模块调用。
下面的示例代码显示了我们如何以编程方式在 java 2014 年 9 月 11 日(仅使用 OpenJDK 版本测试)中找到 JMX 临时端口。
Java 9+ 码:
在下面的代码中,您可以获得 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 模块和 JMX 的 9+ VM 参数:
--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+ 结果:
JavaVersion:14.0
来自 Java 9 Plus:-->service:jmx:rmi:///jndi/rmi://XXXX:50678/jmxrmi
来自 Java 9 Plus:-->service:jmx:rmi:///jndi/rmi://XXXX:50678/jmxrmi
JavaVersion:9.0
来自 Java 9 Plus:-->service:jmx:rmi:///jndi/rmi://XXXX:60342/jmxrmi
来自 Java 9 Plus:-->service:jmx:rmi:///jndi/rmi://XXXX:60342/jmxrmi
编程愉快。
这个问题:sun.management.ConnectorAddressLink
和指定的参数来发现临时 JMX 端口(如果我们使用 com.sun.management.jmxremote.port=0
启动进程)。
但是对于 Java 9+,这些 类 被设为私有并且无法再访问。有什么方法可以通过编程找到 JMX 绑定到哪个端口?
ConnectorAddressLink class 可以通过 jdk.internal.agent 模块调用。
下面的示例代码显示了我们如何以编程方式在 java 2014 年 9 月 11 日(仅使用 OpenJDK 版本测试)中找到 JMX 临时端口。
Java 9+ 码:
在下面的代码中,您可以获得 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 模块和 JMX 的 9+ VM 参数:
--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+ 结果:
JavaVersion:14.0 来自 Java 9 Plus:-->service:jmx:rmi:///jndi/rmi://XXXX:50678/jmxrmi 来自 Java 9 Plus:-->service:jmx:rmi:///jndi/rmi://XXXX:50678/jmxrmi
JavaVersion:9.0 来自 Java 9 Plus:-->service:jmx:rmi:///jndi/rmi://XXXX:60342/jmxrmi 来自 Java 9 Plus:-->service:jmx:rmi:///jndi/rmi://XXXX:60342/jmxrmi
编程愉快。