1. Overview

Understanding the operating system (OS) is crucial in programming for implementing OS-specific behavior.

In this tutorial, we’ll explore Kotlin methods to detect the current OS.

2. Using the System.getProperty() Function

When we run our Kotlin program on JVM, it inherits the powerful System class from Java. This class serves as our gateway to access system-related information. Specifically, we can use the System.getProperty() method to extract details about the OS that the JVM is running on.

The os.name property indicates the OS name, while os.version holds the OS version information.

Let’s create a test function by reading these two properties:

val osName = System.getProperty("os.name")
val osVersion = System.getProperty("os.version")
assertTrue { osName.isNotBlank() }
assertTrue { osVersion.isNotBlank() }

log.info(
    """|
    |OS Information
    |-----------------
    |OS_Name: $osName
    |Version: $osVersion
    |""".trimMargin())

Next, we’ll test this function on two systems to verify its OS reporting accuracy.

Our first test target is an Arch Linux box. Before we start our test function, let’s check its kernel information using the uname command:

$ uname -sr
Linux 6.1.35-1-lts

Now, if we run the test function, it passes and produces the following output:

OS Information
-----------------
OS_Name: Linux
Version: 6.1.35-1-lts

As we can see, our function reports the OS information correctly.

Next, let’s move to a MacBook that is running the following system:

$ sw_vers
ProductName:            macOS
ProductVersion:         14.2.1
...

If we execute our function, it produces the expected OS data again:

OS_Name: Mac OS X
Version: 14.2.1

Therefore, we can obtain OS information by reading the os.name and os.version properties.

In practice, we usually determine the OS by checking whether the os.name property contains specific keywords. For example, we can achieve that using Kotlin’s when block:

val osName = System.getProperty("os.name").lowercase()
assertTrue { osName.isNotBlank() }

val result = when {
    "windows" in osName -> "Windows"
    listOf("mac", "nix", "sunos", "solaris", "bsd").any { it in osName } -> "*nix"
    else -> "Other"
}

log.info(">>> $osName -> $result")

Let’s run this on our Linux and Mac systems.

On Linux we see:

>>> linux -> *nix

And on the MacBook we see:

>>> mac os x -> *nix

The code example is straightforward. However, it’s worth noting that for comprehensive coverage of *nix systems, we must manually fill the system names in the list, which is error-prone. In this example, AIX (“aix“), HP-UX (“hp-ux“), and Irix (“irix“) are missing from the list.

Additionally, we might need to determine the OS versions, for instance, to distinguish Windows 2000, Windows Vista, and Windows 10. This often involves multiple string matching checks and is error-prone.

Therefore, some libraries provide utility classes for convenience OS information retrieval.

Next, let’s look at an example.

3. Using SystemUtils From Apache Commons Lang 3

Apache Commons Lang 3 is a widely used library. Its SystemUtils class serves as a central hub for conveniently retrieving various OS information and environment data. The SysemUtils class internally also reads system properties like os.name and os.version to gather OS data.

Let’s use it to check what OS family we’re running on:

val osName = SystemUtils.OS_NAME
val osVersion = SystemUtils.OS_VERSION
assertTrue { osName.isNotBlank() }
assertTrue { osVersion.isNotBlank() }

log.info(
    """|
    |OS Information
    |-----------------
    |OS_Name   : $osName
    |Version   : $osVersion
    |Is Windows: ${SystemUtils.IS_OS_WINDOWS}
    |Is *nix   : ${SystemUtils.IS_OS_UNIX}
    |Is Mac OS : ${SystemUtils.IS_OS_MAC}
    |""".trimMargin())

As the code above shows, we can directly access predefined static properties in SystemUtils to obtain the required OS information. For instance, IS_OS_UNIX tells if the system is *nix, and it covers all *nix systems we noted earlier. IS_OS_MAC reports if the system is macOS. Similarly, we can check the Windows version by checking IS_OS_WINDOWS_2000, IS_OS_WINDOWS_VISTA, IS_OS_WINDOWS_10, etc.

After executing this test function on our Linux system and MacBook, we can see SystemUtils yields accurate results.

Here’ what we get on Linux:

OS Information
-----------------
OS_Name   : Linux
Version   : 6.1.35-1-lts
Is Windows: false
Is *nix   : true
Is Mac OS : false

And, the below is on MacBook:

OS Information
-----------------
OS_Name   : Mac OS X
Version   : 14.2.1
Is Windows: false
Is *nix   : true
Is Mac OS : true

4. Conclusion

In this article, we explored two ways to obtain the OS data:

  • Reading the os.name and the os.version system properties
  • Using SystemUtils from Apache Commons Lang 3

As always, the complete source code for the examples is available over on GitHub.