--- old/src/java.management/share/classes/javax/management/remote/JMXServiceURL.java 2016-01-27 12:20:37.216124876 +0530 +++ new/src/java.management/share/classes/javax/management/remote/JMXServiceURL.java 2016-01-27 12:20:37.052124878 +0530 @@ -34,10 +34,15 @@ import java.io.ObjectInputStream; import java.io.Serializable; +import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.MalformedURLException; +import java.net.NetworkInterface; +import java.net.SocketException; import java.net.UnknownHostException; import java.util.BitSet; +import java.util.Enumeration; import java.util.Locale; import java.util.StringTokenizer; @@ -236,10 +241,13 @@ * @param protocol the protocol part of the URL. If null, defaults * to jmxmp. * - * @param host the host part of the URL. If null, defaults to the - * local host name, as determined by - * InetAddress.getLocalHost().getHostName(). If it - * is a numeric IPv6 address, it can optionally be enclosed in + * @param host the host part of the URL. If host is null and if + * local host name can be resolved to an IP, then host defaults + * to local host name as determined by + * InetAddress.getLocalHost().getHostName(). If host is null + * and if local host name cannot be resolved to an IP, then host + * defaults to numeric IP address of one of the active network interfaces. + * If host is a numeric IPv6 address, it can optionally be enclosed in * square brackets []. * * @param port the port part of the URL. @@ -260,10 +268,13 @@ * @param protocol the protocol part of the URL. If null, defaults * to jmxmp. * - * @param host the host part of the URL. If null, defaults to the - * local host name, as determined by - * InetAddress.getLocalHost().getHostName(). If it - * is a numeric IPv6 address, it can optionally be enclosed in + * @param host the host part of the URL. If host is null and if + * local host name can be resolved to an IP, then host defaults + * to local host name as determined by + * InetAddress.getLocalHost().getHostName(). If host is null + * and if local host name cannot be resolved to an IP, then host + * defaults to numeric IP address of one of the active network interfaces. + * If host is a numeric IPv6 address, it can optionally be enclosed in * square brackets []. * * @param port the port part of the URL. @@ -286,32 +297,40 @@ InetAddress local; try { local = InetAddress.getLocalHost(); - } catch (UnknownHostException e) { - throw new MalformedURLException("Local host name unknown: " + - e); - } - - host = local.getHostName(); - - /* We might have a hostname that violates DNS naming + host = local.getHostName(); + + /* We might have a hostname that violates DNS naming rules, for example that contains an `_'. While we could be strict and throw an exception, this is rather user-hostile. Instead we use its numerical IP address. We can only reasonably do this for the host==null case. If we're given an explicit host name that is illegal we have to reject it. (Bug 5057532.) */ - try { - validateHost(host, port); - } catch (MalformedURLException e) { - if (logger.fineOn()) { + try{ + validateHost(host, port); + }catch (MalformedURLException e){ + if (logger.fineOn()) { logger.fine("JMXServiceURL", "Replacing illegal local host name " + host + " with numeric IP address " + "(see RFC 1034)", e); } host = local.getHostAddress(); - /* Use the numeric address, which could be either IPv4 - or IPv6. validateHost will accept either. */ + } + } catch (UnknownHostException e) { + try { + /* + If hostname cannot be resolved, we will try and use numeric IPv4/IPv6 address. + If host==null, we know that agent will be started on all interfaces - 0.0.0.0 + Hence we will use IP address of first active non-loopback interface + */ + host = getActiveNetworkInterfaceIP(); + if(host == null){ + throw new MalformedURLException("Unable to resolve hostname or get valid IP address"); + } + } catch (SocketException ex) { + throw new MalformedURLException("Unable to resolve hostname or get valid IP address"); + } } } @@ -339,6 +358,32 @@ validate(); } + + private String getActiveNetworkInterfaceIP() throws SocketException{ + Enumeration networkInterface = NetworkInterface.getNetworkInterfaces(); + String ipv6AddrStr = null; + while (networkInterface.hasMoreElements()) + { + NetworkInterface nic = networkInterface.nextElement(); + if(nic.isUp() && !nic.isLoopback()){ + Enumeration inet = nic.getInetAddresses(); + while (inet.hasMoreElements()) + { + InetAddress addr = inet.nextElement(); + if (addr instanceof Inet4Address && !addr.isLinkLocalAddress()){ + return addr.getHostAddress(); + }else if (addr instanceof Inet6Address && !addr.isLinkLocalAddress()){ + /* + We save last seen IPv6 address which we will return + if we do not find any interface with IPv4 address. + */ + ipv6AddrStr = addr.getHostAddress(); + } + } + } + } + return ipv6AddrStr; + } private static final String INVALID_INSTANCE_MSG = "Trying to deserialize an invalid instance of JMXServiceURL"; @@ -540,7 +585,9 @@ * constructor that takes a separate host parameter, the result is * the string that was specified. If that string was null, the * result is - * InetAddress.getLocalHost().getHostName().

+ * InetAddress.getLocalHost().getHostName() if local host name + * can be resolved to an IP. Else numeric IP address of an active + * network interface will be used.

* *

In either case, if the host was specified using the * [...] syntax for numeric IPv6 addresses, the