This question: When using a JMX server with ephemeral port, how to get the server port number? 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
).
However for Java 9+, these classes were made private and can no longer be accessed. Is there any way one could programmatically find which port JMX has bound to?
The default port for secure JMX access is 9875 and the default username and password are admin and springsource .
The JMX Messaging Protocol (JMXMP) connector is a configuration of the generic connector where the transport protocol is based on TCP and the object wrapping is native Java serialization.
JMX is a generic API for publishing an interface to monitor the internals of a Java application ( A Java version of SNMP ). RMI is for Remote Method Invocation a Java specific implementation of a Remote Procedure Call interface, they are not related at all.
ConnectorAddressLink class can be invoked via jdk.internal.agent module.
Below sample code shows how we can programmatically find JMX ephemeral port in java 9/11/14 (Tested with OpenJDK versions only).
Java 9+ Code:
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.
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:
--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 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
Happy programming.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With