5

I am using below code to print out hostname of a linux box using java 1.5

public static void main(String a[]) {
    System.out.println( InetAddress.getLocalHost().getCanonicalHostName() );
}

When I have hostname of the system a 64 char length string, the code just prints 'localhost.localdomain'. If my hostname length is less than 64, it prints out the hostname correctly. The max hostname length for the system is 64 (getconf HOST_NAME_MAX gives 64)

What could be wrong here? Could this be a bug (though, I am inclined to think problem is on my side)

Thanks for help!

Nishan
  • 2,821
  • 4
  • 27
  • 36

2 Answers2

4

What is likely to happen on Linux is that InetAddress.getLocalHost() will return the loopback address (in 127/8, usually 127.0.0.1). Thus the name taken from the /etc/hosts file likely to be localhost.localdomain.

In order to get the correct address / host name, you can use the following code instead, that will list all IP address associated with a network interface (eth0 in my example), and we'll select the IPv4 one, that does not belong to the loopback class.

try {
    // Replace eth0 with your interface name
    NetworkInterface i = NetworkInterface.getByName("eth0");

    if (i != null) {

        Enumeration<InetAddress> iplist = i.getInetAddresses();

        InetAddress addr = null;

        while (iplist.hasMoreElements()) {
            InetAddress ad = iplist.nextElement();
            byte bs[] = ad.getAddress();
            if (bs.length == 4 && bs[0] != 127) {
                addr = ad;
                // You could also display the host name here, to 
                // see the whole list, and remove the break.
                break;
            }
        }

        if (addr != null) {
            System.out.println( addr.getCanonicalHostName() );
        }
    } catch (...) { ... }

You could change a bit the code to display all addresses, see the comments inside the code.

edit

You might want also to iterate over other NICs, as suggested by @rafalmag

instead of NetworkInterface.getByName("eth0") I suggest to iterate over NetworkInterface.getNetworkInterfaces()

Déjà vu
  • 28,223
  • 6
  • 72
  • 100
  • Yes, this works. But I still like to know what is wrong with my code, or what is wrong with the JVM. I guess I'll keep looking. – Nishan Feb 03 '11 at 03:33
  • 1
    @Nishan I don't think the problem is linked with 64 chars. On Linux, `getLocalHost()` returns the loopback. Unless you change the `/etc/hosts` you will get the `localhost.localdomain`. It is not a bug (same behavior on my own server - I use the code above as well). – Déjà vu Feb 03 '11 at 03:36
  • Oh yes, I have valid entry in /etc/hosts. My /etc/hosts file looks like this : `127.0.0.1 localhost.localdomain 192.168.1.2 <64_char_hostname> ` – Nishan Feb 03 '11 at 09:56
  • From [code](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/net/InetAddress.java#InetAddress.getLocalHost%28%29), getLocalHost() gets hostname by calling Inet4AddressImpl.getLocalHostName() and then resolves the address associated with that hostname from /etc/hosts or dns. – Nishan Feb 03 '11 at 10:03
  • Looking [here](http://icedtea.classpath.org/~vanaltj/webrevs/tl/patch1/jdk/src/solaris/native/java/net/Inet4AddressImpl.c.html) it seems like problem is with JVM code. Line 68, ` if (JVM_GetHostName(hostname, MAXHOSTNAMELEN)) {` should be ` if (JVM_GetHostName(hostname, sizeof(hostname))) {`. This is what I could make out. I am not very sure if this is the same file used in Sun JVM, I am having a hard time looking up JVM source code. – Nishan Feb 03 '11 at 11:52
  • @Nishan If you 127.0.0.1 IP address has as name localhost.localdomain, this is what will be selected. The solution above will work in any case. – Déjà vu Feb 03 '11 at 12:28
  • @ring0 :your solution works perfect. But then, my question was what is wrong with my code (or corresponding Java code it uses). – Nishan Feb 11 '11 at 05:22
  • @Nishan The `InetAddress.getLocalHost()` method on Linux returns the loopback address (127.0.0.1). For that address, the `getCanonicalHostName()` methods returns its name from the `/etc/hosts` file: localhost.localdomain. Using my method above, you search for the address being not the loopback. This it returns the IP address of the interface, and `getCanonicalHostName()` its name. – Déjà vu Feb 11 '11 at 05:36
  • @ring0 actually, when I have my hostname less than 64 chars, `InetAddress.getLocalHost().getCanonicalHostName()` returns whatever I get when I run `hostname` command in the shell. For exactly 64 chars, it returns localhost. This is what is intriguing me. – Nishan Feb 14 '11 at 13:50
  • 1
    instead of NetworkInterface.getByName("eth0") I suggest to iterate over NetworkInterface.getNetworkInterfaces() – rafalmag Oct 08 '12 at 08:00
1

It's hard to guess what might be going wrong in your case, but based on the corresponding code from Java 6, it could be as simple as a name resolution problem, or possibly Java falsely thinking that your 64 character hostname is spoofed.

earldouglas
  • 13,265
  • 5
  • 41
  • 50
  • I think the issue is with Inet4AddressImpl.getLocalHostName() which is a native method. I am yet to verify this, will keep you posted. – Nishan Feb 03 '11 at 03:32