[java] Recommended way to get hostname in Java

Which of the following is the best and most portable way to get the hostname of the current computer in Java?

Runtime.getRuntime().exec("hostname")

vs

InetAddress.getLocalHost().getHostName()

The answer is


Although this topic has already been answered there's more to say.

First of all: Clearly we need some definitions here. The InetAddress.getLocalHost().getHostName() gives you the name of the host as seen from a network perspective. The problems with this approach are well documented in the other answers: it often requires a DNS lookup, it's ambiguous if the host has multiple network interfaces and it just plain fails sometimes (see below).

But on any OS there's another name as well. A name of the host that gets defined very early in the boot process, long before the network is initialized. Windows refers to this as computername, Linux calls it kernel hostname and Solaris uses the word nodename. I like best the word computername, so I'll use that word from now on.

Finding the computername

  • On Linux/Unix the computername is what you get from the C function gethostname(), or hostname command from shell or HOSTNAME environment variable in Bash-like shells.

  • On Windows the computername is what you get from environment variable COMPUTERNAME or Win32 GetComputerName function.

Java has no way of obtaining what I've defined as 'computername'. Sure, there are workarounds as described in other answers, like for Windows calling System.getenv("COMPUTERNAME"), but on Unix/Linux there's no good workaround without resorting to JNI/JNA or Runtime.exec(). If you don't mind a JNI/JNA solution then there's gethostname4j which is dead simple and very easy to use.

Let's move on with two examples, one from Linux and one from Solaris, which demonstrate how you can easily get into a situation where you cannot obtain the computername using standard Java methods.

Linux example

On a newly created system, where the host during installation has been named as 'chicago', we now change the so-called kernel hostname:

$ hostnamectl --static set-hostname dallas

Now the kernel hostname is 'dallas', as evident from the hostname command:

$ hostname
dallas

But we still have

$ cat /etc/hosts
127.0.0.1   localhost
127.0.0.1   chicago

There's no misconfiguration in this. It just means the host's networked name (or rather the name of the loopback interface) is different from the host's computername.

Now, try executing InetAddress.getLocalHost().getHostName() and it will throw java.net.UnknownHostException. You are basically stuck. There's no way to retrieve neither the value 'dallas' nor the value 'chicago'.

Solaris example

The example below is based on Solaris 11.3.

The host has deliberately been configured so that the loopback name <> nodename.

In other words we have:

$ svccfg -s system/identity:node listprop config
...
...
config/loopback             astring        chicago
config/nodename             astring        dallas

and the contents of /etc/hosts :

:1 chicago localhost
127.0.0.1 chicago localhost loghost

and the result of the hostname command would be:

$ hostname
dallas

Just like in the Linux example a call to InetAddress.getLocalHost().getHostName() will fail with

java.net.UnknownHostException: dallas:  dallas: node name or service name not known

Just like the Linux example you are now stuck. There's no way to retrieve neither the value 'dallas' nor the value 'chicago'.

When will you really struggle with this?

Very often you'll find that InetAddress.getLocalHost().getHostName() will indeed return a value which is equal to the computername. So there's no problem (except for the added overhead of name resolution).

The problem arises typically within PaaS environments where there's a difference between computername and the name of the loopback interface. For example people report problems in Amazon EC2.

Bug/RFE reports

A bit of searching reveals this RFE report : link1, link2. However, judging from the comments on that report the issue seems to have been largely misunderstood by the JDK team, so it is unlikely it will be addressed.

I like the comparison in the RFE to other programming languages.


The most portable way to get the hostname of the current computer in Java is as follows:

import java.net.InetAddress;
import java.net.UnknownHostException;

public class getHostName {

    public static void main(String[] args) throws UnknownHostException {
        InetAddress iAddress = InetAddress.getLocalHost();
        String hostName = iAddress.getHostName();
        //To get  the Canonical host name
        String canonicalHostName = iAddress.getCanonicalHostName();

        System.out.println("HostName:" + hostName);
        System.out.println("Canonical Host Name:" + canonicalHostName);
    }
}

hostName == null;
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
{
    while (interfaces.hasMoreElements()) {
        NetworkInterface nic = interfaces.nextElement();
        Enumeration<InetAddress> addresses = nic.getInetAddresses();
        while (hostName == null && addresses.hasMoreElements()) {
            InetAddress address = addresses.nextElement();
            if (!address.isLoopbackAddress()) {
                hostName = address.getHostName();
            }
        }
    }
}

Environment variables may also provide a useful means -- COMPUTERNAME on Windows, HOSTNAME on most modern Unix/Linux shells.

See: https://stackoverflow.com/a/17956000/768795

I'm using these as "supplementary" methods to InetAddress.getLocalHost().getHostName(), since as several people point out, that function doesn't work in all environments.

Runtime.getRuntime().exec("hostname") is another possible supplement. At this stage, I haven't used it.

import java.net.InetAddress;
import java.net.UnknownHostException;

// try InetAddress.LocalHost first;
//      NOTE -- InetAddress.getLocalHost().getHostName() will not work in certain environments.
try {
    String result = InetAddress.getLocalHost().getHostName();
    if (StringUtils.isNotEmpty( result))
        return result;
} catch (UnknownHostException e) {
    // failed;  try alternate means.
}

// try environment properties.
//      
String host = System.getenv("COMPUTERNAME");
if (host != null)
    return host;
host = System.getenv("HOSTNAME");
if (host != null)
    return host;

// undetermined.
return null;

InetAddress.getLocalHost().getHostName() is better (as explained by Nick), but still not very good

One host can be known under many different hostnames. Usually you'll be looking for the hostname your host has in a specific context.

For example, in a web application, you might be looking for the hostname used by whoever issued the request you're currently handling. How to best find that one depends on which framework you're using for your web application.

In some kind of other internet-facing service, you'll want the hostname your service is available through from the 'outside'. Due to proxies, firewalls etc this might not even be a hostname on the machine your service is installed on - you might try to come up with a reasonable default, but you should definitely make this configurable for whoever installs this.


Just one-liner ... cross platform (Windows-Linux-Unix-Mac(Unix)) [Always works, No DNS required]:

String hostname = new BufferedReader(
    new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream()))
   .readLine();

You're done !!


If you're not against using an external dependency from maven central, I wrote gethostname4j to solve this problem for myself. It just uses JNA to call libc's gethostname function (or gets the ComputerName on Windows) and returns it to you as a string.

https://github.com/mattsheppard/gethostname4j


InetAddress.getLocalHost().getHostName() is the best way out of the two as this is the best abstraction at the developer level.


As others have noted, getting the hostname based on DNS resolution is unreliable.

Since this question is unfortunately still relevant in 2018, I'd like to share with you my network-independent solution, with some test runs on different systems.

The following code tries to do the following:

  • On Windows

    1. Read the COMPUTERNAME environment variable through System.getenv().

    2. Execute hostname.exe and read the response

  • On Linux

    1. Read the HOSTNAME environment variable through System.getenv()

    2. Execute hostname and read the response

    3. Read /etc/hostname (to do this I'm executing cat since the snippet already contains code to execute and read. Simply reading the file would be better, though).

The code:

public static void main(String[] args) throws IOException {
    String os = System.getProperty("os.name").toLowerCase();

    if (os.contains("win")) {
        System.out.println("Windows computer name through env:\"" + System.getenv("COMPUTERNAME") + "\"");
        System.out.println("Windows computer name through exec:\"" + execReadToString("hostname") + "\"");
    } else if (os.contains("nix") || os.contains("nux") || os.contains("mac os x")) {
        System.out.println("Unix-like computer name through env:\"" + System.getenv("HOSTNAME") + "\"");
        System.out.println("Unix-like computer name through exec:\"" + execReadToString("hostname") + "\"");
        System.out.println("Unix-like computer name through /etc/hostname:\"" + execReadToString("cat /etc/hostname") + "\"");
    }
}

public static String execReadToString(String execCommand) throws IOException {
    try (Scanner s = new Scanner(Runtime.getRuntime().exec(execCommand).getInputStream()).useDelimiter("\\A")) {
        return s.hasNext() ? s.next() : "";
    }
}

Results for different operating systems:

macOS 10.13.2

Unix-like computer name through env:"null"
Unix-like computer name through exec:"machinename
"
Unix-like computer name through /etc/hostname:""

OpenSuse 13.1

Unix-like computer name through env:"machinename"
Unix-like computer name through exec:"machinename
"
Unix-like computer name through /etc/hostname:""

Ubuntu 14.04 LTS This one is kinda strange since echo $HOSTNAME returns the correct hostname, but System.getenv("HOSTNAME") does not:

Unix-like computer name through env:"null"
Unix-like computer name through exec:"machinename
"
Unix-like computer name through /etc/hostname:"machinename
"

EDIT: According to legolas108, System.getenv("HOSTNAME") works on Ubuntu 14.04 if you run export HOSTNAME before executing the Java code.

Windows 7

Windows computer name through env:"MACHINENAME"
Windows computer name through exec:"machinename
"

Windows 10

Windows computer name through env:"MACHINENAME"
Windows computer name through exec:"machinename
"

The machine names have been replaced but I kept the capitalization and structure. Note the extra newline when executing hostname, you might have to take it into account in some cases.


InetAddress.getLocalHost().getHostName() is the more portable way.

exec("hostname") actually calls out to the operating system to execute the hostname command.

Here are a couple other related answers on SO:

EDIT: You should take a look at A.H.'s answer or Arnout Engelen's answer for details on why this might not work as expected, depending on your situation. As an answer for this person who specifically requested portable, I still think getHostName() is fine, but they bring up some good points that should be considered.


Strictly speaking - you have no choice but calling either hostname(1) or - on Unix gethostname(2). This is the name of your computer. Any attempt to determine the hostname by an IP address like this

InetAddress.getLocalHost().getHostName()

is bound to fail in some circumstances:

  • The IP address might not resolve into any name. Bad DNS setup, bad system setup or bad provider setup may be the reason for this.
  • A name in DNS can have many aliases called CNAMEs. These can only be resolved in one direction properly: name to address. The reverse direction is ambiguous. Which one is the "official" name?
  • A host can have many different IP addresses - and each address can have many different names. Two common cases are: One ethernet port has several "logical" IP addresses or the computer has several ethernet ports. It is configurable whether they share an IP or have different IPs. This is called "multihomed".
  • One Name in DNS can resolve to several IP Addresses. And not all of those addresses must be located on the same computer! (Usecase: A simple form of load-balancing)
  • Let's not even start talking about dynamic IP addresses.

Also don't confuse the name of an IP-address with the name of the host (hostname). A metaphor might make it clearer:

There is a large city (server) called "London". Inside the city walls much business happens. The city has several gates (IP addresses). Each gate has a name ("North Gate", "River Gate", "Southampton Gate"...) but the name of the gate is not the name of the city. Also you cannot deduce the name of the city by using the name of a gate - "North Gate" would catch half of the bigger cities and not just one city. However - a stranger (IP packet) walks along the river and asks a local: "I have a strange address: 'Rivergate, second left, third house'. Can you help me?" The local says: "Of course, you are on the right road, simply go ahead and you will arrive at your destination within half an hour."

This illustrates it pretty much I think.

The good news is: The real hostname is usually not necessary. In most cases any name which resolves into an IP address on this host will do. (The stranger might enter the city by Northgate, but helpful locals translate the "2nd left" part.)

In the remaining corner cases you must use the definitive source of this configuration setting - which is the C function gethostname(2). That function is also called by the program hostname.


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to network-programming

Difference between PACKETS and FRAMES socket connect() vs bind() How to read all of Inputstream in Server Socket JAVA C# An established connection was aborted by the software in your host machine Asynchronous Function Call in PHP TCP: can two different sockets share a port? trace a particular IP and port How is TeamViewer so fast? Recommended way to get hostname in Java Difference between TCP and UDP?

Examples related to environment-variables

Using Environment Variables with Vue.js Adding an .env file to React Project Is there any way to set environment variables in Visual Studio Code? Test process.env with Jest How to set environment variables in PyCharm? ARG or ENV, which one to use in this case? how to set ASPNETCORE_ENVIRONMENT to be considered for publishing an asp.net core application? What is a good practice to check if an environmental variable exists or not? Passing bash variable to jq Tensorflow set CUDA_VISIBLE_DEVICES within jupyter

Examples related to hostname

How to get hostname from IP (Linux)? Can I map a hostname *and* a port with /etc/hosts? Get hostname of current request in node.js Express Recommended way to get hostname in Java Java SSL: how to disable hostname verification How can I use Python to get the system hostname? Python lookup hostname from IP with 1 second timeout How to extract the hostname portion of a URL in JavaScript How to store the hostname in a variable in a .bat file? how to find host name from IP with out login to the host