How do I programmatically determine operating system in Java?
I would like to determine the operating system of the host that my Java program is running programmatically (for example: I would like to be able to load different properties based on whether I am on a Windows or Unix platform). What is the safest way to do this with 100% reliability?
22 Answers 22
P.S. You may find this code useful:
All it does is print out all the properties provided by your Java implementations. It’ll give you an idea of what you can find out about your Java environment via properties. 🙂
As indicated in other answers, System.getProperty provides the raw data. However, the Apache Commons Lang component provides a wrapper for java.lang.System with handy properties like SystemUtils.IS_OS_WINDOWS , much like the aforementioned Swingx OS util.
I would recommend to cache it in a static variable:
public static final class OsUtils < private static String OS = null; public static String getOsName() < if(OS == null) < OS = System.getProperty("os.name"); >return OS; > public static boolean isWindows() < return getOsName().startsWith("Windows"); >public static boolean isUnix() // and so on >
That way, every time you ask for the Os, you do not fetch the property more than once in the lifetime of your application.
February 2016: 7+ years later:
There is a bug with Windows 10 (which did not exist at the time of the original answer).
See «Java’s “os.name” for Windows 10?»
I agree with the getOSName function, on the basis of OAOO (once and only once); however, the caching is totally redundant given the speed of hash lookups.
Totally redundant might be a bit harsh, hash lookups are more expensive than accessing a reference. It all depends on the context.
I reread this answer. If you are going to cache, cache the values of isWindows , isUnix , etc. That way you save on the string comparison time also.
some of the links in the answers above seem to be broken. I have added pointers to current source code in the code below and offer an approach for handling the check with an enum as an answer so that a switch statement can be used when evaluating the result:
OsCheck.OSType ostype=OsCheck.getOperatingSystemType(); switch (ostype)
/** * helper class to check the operating system this Java VM runs in * * please keep the notes below as a pseudo-license * * http://stackoverflow.com/questions/228477/how-do-i-programmatically-determine-operating-system-in-java * compare to http://svn.terracotta.org/svn/tc/dso/tags/2.6.4/code/base/common/src/com/tc/util/runtime/Os.java * http://www.docjar.com/html/api/org/apache/commons/lang/SystemUtils.java.html */ import java.util.Locale; public static final class OsCheck < /** * types of Operating Systems */ public enum OSType < Windows, MacOS, Linux, Other >; // cached result of OS detection protected static OSType detectedOS; /** * detect the operating system from the os.name System property and cache * the result * * @returns - the operating system detected */ public static OSType getOperatingSystemType() < if (detectedOS == null) < String OS = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH); if ((OS.indexOf("mac") >= 0) || (OS.indexOf("darwin") >= 0)) < detectedOS = OSType.MacOS; >else if (OS.indexOf("win") >= 0) < detectedOS = OSType.Windows; >else if (OS.indexOf("nux") >= 0) < detectedOS = OSType.Linux; >else < detectedOS = OSType.Other; >> return detectedOS; > >
The code above may have locale issues, since it uses toLowerCase(), which is locale sensitive. Where this matters is particularly when converting i’s to lower/upper case, since in Turkey, I becomes lower case undotted i (ı), and i becomes upper case dotted i (İ). So «WINDOWS».toLowerCase().indexOf(«win») will return -1 in Turkey. Always pass a locale when doing a lower case of a particular language, ie «WINDOWS».toLowerCase(Locale.ENGLISH).indexOf(«win») will work in Turkey.
The following JavaFX classes have static methods to determine current OS (isWindows(),isLinux(). ):
- com.sun.javafx.PlatformUtil
- com.sun.media.jfxmediaimpl.HostUtils
- com.sun.javafx.util.Utils
Please note that the access to «com/sun/javafx/*» is discouraged now (checked it with JDK 1.8.0_121).
@HummelingEngineeringBV: I guess it was a mistake from my side. I am working with eclipse Neon 4.6.3 and the «Java Build Path» shows several «Discouraged: com/sun/javafx/**» warnings. However, as I found out, this happens to be an eclipse-bug and/or -feature (see link).
I have to correct myself one more time. Beginning with Java 9/10+, several «com.sun.*» packages/APIs are about to be removed. Check out this link for more info. I actually stumbled over this because we use some of these packages. Migrating to eclipse 4.8/JDK 10, we now have to fix these and several other compiler errors due to missing references.
For accessing OS use: System.getProperty(«os.name») .
But WAIT.
Why not create a utility class, make it reusable! And probably much faster on multiple calls. Clean, clear, faster!
Create a Util class for such utility functions. Then create public enums for each operating system type.
public class Util < public enum OS < WINDOWS, LINUX, MAC, SOLARIS >;// Operating systems. private static OS os = null; public static OS getOS() < if (os == null) < String operSys = System.getProperty("os.name").toLowerCase(); if (operSys.contains("win")) < os = OS.WINDOWS; >else if (operSys.contains("nix") || operSys.contains("nux") || operSys.contains("aix")) < os = OS.LINUX; >else if (operSys.contains("mac")) < os = OS.MAC; >else if (operSys.contains("sunos")) < os = OS.SOLARIS; >> return os; > >
Now, you can easily invoke class from any class as follows,(P.S. Since we declared os variable as static, it will consume time only once to identify the system type, then it can be used until your application halts. )
I want to use this piece of code in an open-source project (github.com/openhab/openhab-addons), is this okay with you?
Go ahead and put rationale for why you said so. I am happy to change the code if you have any reasonable evidence. Be reasonable and clarify your comment please, so that I can improve my 7-8 years old answer.
A small example of what you’re trying to achieve would probably be a class similar to what’s underneath:
import java.util.Locale; public class OperatingSystem < private static String OS = System.getProperty("os.name", "unknown").toLowerCase(Locale.ROOT); public static boolean isWindows() < return OS.contains("win"); >public static boolean isMac() < return OS.contains("mac"); >public static boolean isUnix() < return OS.contains("nux"); >>
This particular implementation is quite reliable and should be universally applicable. Just copy and paste it into your class of choice.
Why make it so complicated? System.getProperty(«os.name») is sufficient. Don’t bother with the unnecessary fluff.
System.getProperty("os.name"); System.getProperty("os.version"); System.getProperty("os.arch");
If you’re interested in how an open source project does stuff like this, you can check out the Terracotta class (Os.java) that handles this junk here:
And you can see a similar class to handle JVM versions (Vm.java and VmVersion.java) here:
also suffers from the same issue identified by James Roper in Wolfgang Fahl’s answer — use of toLowerCase without specifying a locale
I think following can give broader coverage in fewer lines
import org.apache.commons.exec.OS; if (OS.isFamilyWindows()) < //load some property >else if (OS.isFamilyUnix()) < //load some other property >
If you’re working in a security sensitive environment, then please read this through.
Please refrain from ever trusting a property obtained via the System#getProperty(String) subroutine! Actually, almost every property including os.arch , os.name , and os.version isn’t readonly as you’d might expect — instead, they’re actually quite the opposite.
First of all, any code with sufficient permission of invoking the System#setProperty(String, String) subroutine can modify the returned literal at will. However, that’s not necessarily the primary issue here, as it can be resolved through the use of a so called SecurityManager , as described in greater detail over here.
The actual issue is that any user is able to edit these properties when running the JAR in question (through -Dos.name= , -Dos.arch= , etc.). A possible way to avoid tampering with the application parameters is by querying the RuntimeMXBean as shown here. The following code snippet should provide some insight into how this may be achieved.
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean(); List arguments = runtimeMxBean.getInputArguments(); for (String argument : arguments) < if (argument.startsWith("-Dos.name") < // System.getProperty("os.name") altered >else if (argument.startsWith("-Dos.arch") < // System.getProperty("os.arch") altered >>
How to know JDK version from within Java code
I presume you mean just the Java version, in which case try this:
String version = System.getProperty("java.version");
Relying on the java.version string for anything else than showing to a human is fragile and will break if running on another Java implementation.
The only reliable way programatically is to use reflection to carefully ask if a given facility is available, and then select the appropriate code accordingly.
@Jesse, I’d rather put it the other way around. What rule would you set up for analyzing the java.version string?
@Jesse, I was unaware of this property. I can, however, not see from a quick look in the JLS that it is guaranteed to be present and containing a valid number. Perhaps you know where it says so?
@Jesse, the crucial question here if this is for Hotspot-based JVM’s only. I cannot immediately tell.
Don’t use Float.valueOf like @JesseBarnum. This failed for me because 1.8>=1.8 returned false for me, due to round-off errors. Use .compareTo(«1.8»)>=0 instead.
System.out.println(Runtime.version());
Prints something like 17.0.2+8-86
System.out.println("Java Feature Version = " + Runtime.version().feature()); System.out.println("Java Interim Version = " + Runtime.version().interim()); System.out.println("Java Update Version = " + Runtime.version().update()); System.out.println("Java Version Build = " + Runtime.version().build().map(String::valueOf).orElse("Unknown")); System.out.println("Java Version Pre-Release Info = " + Runtime.version().pre().orElse("N/A"));
Java Feature Version = 17 Java Interim Version = 0 Java Update Version = 2 Java Version Build = 8 Java Version Pre-Release Info = N/A
How do I find Java version?
The simplest way to get the Java version is by running the java -version command in your terminal application or Windows command prompt. If Java is installed and available on your path you can get information like below.
java -version java version "17" 2021-09-14 LTS Java(TM) SE Runtime Environment (build 17+35-LTS-2724) Java HotSpot(TM) 64-Bit Server VM (build 17+35-LTS-2724, mixed mode, sharing)
Using System Properties
But if you want to get Java version from your Java class or application you can obtain the Java version by calling the System.getProperty() method and provide the property key as argument. Here are some property keys that related to Java version that you can read from the system properties.
package org.kodejava.lang; public class JavaVersion < public static void main(String[] args) < String version = System.getProperty("java.version"); String versionDate = System.getProperty("java.version.date"); String runtimeVersion = System.getProperty("java.runtime.version"); String vmVersion = System.getProperty("java.vm.version"); String classVersion = System.getProperty("java.class.version"); String specificationVersion = System.getProperty("java.specification.version"); String vmSpecificationVersion = System.getProperty("java.vm.specification.version"); System.out.println("java.version: " + version); System.out.println("java.version.date: " + versionDate); System.out.println("java.runtime.version: " + runtimeVersion); System.out.println("java.vm.version: " + vmVersion); System.out.println("java.class.version: " + classVersion); System.out.println("java.specification.version: " + specificationVersion); System.out.println("java.vm.specification.version: " + vmSpecificationVersion); >>
Running the code above give you output like the following:
java.version: 17 java.version.date: 2021-09-14 java.runtime.version: 17+35-LTS-2724 java.vm.version: 17+35-LTS-2724 java.class.version: 61.0 java.specification.version: 17 java.vm.specification.version: 17
Using Runtime.version()
Since JDK 9 we can use Runtime.version() to get Java runtime version. The feature() , interim() , update and patch() methods of the Runtime.Version class are added in JDK 10. These methods is a replacement for the major() , minor() and security() methods of JDK 9.
Below is the code snippet that demonstrate the Runtime.version() .
package org.kodejava.lang; public class RuntimeVersion < public static void main(String[] args) < System.out.println("Version: " + Runtime.version()); System.out.println("Feature: " + Runtime.version().feature()); System.out.println("Interim: " + Runtime.version().interim()); System.out.println("Update: " + Runtime.version().update()); System.out.println("Patch: " + Runtime.version().patch()); System.out.println("Pre: " + Runtime.version().pre().orElse("")); System.out.println("Build: " + Runtime.version().build().orElse(null)); System.out.println("Optional: " + Runtime.version().optional().orElse("")); >>
Running the code snippet above produce the following output:
Version: 17+35-LTS-2724 Feature: 17 Interim: 0 Update: 0 Patch: 0 Pre: Build: 35 Optional: LTS-2724
Here are the summary of outputs running the above code using some JDKs installed on my machine.
Version | Feature | Interim | Update | Patch | Pre | Build | Optional |
---|---|---|---|---|---|---|---|
10.0.2+13 | 10 | 0 | 2 | 0 | 13 | ||
11.0.6+8-LTS | 11 | 0 | 6 | 0 | 8 | LTS | |
12.0.2+10 | 12 | 0 | 2 | 0 | 10 | ||
13.0.2+8 | 13 | 0 | 2 | 0 | 8 | ||
14+36-1461 | 14 | 0 | 0 | 0 | 36 | 1461 | |
15.0.2+7-27 | 15 | 0 | 2 | 0 | 7 | 27 | |
17+35-LTS-2724 | 17 | 0 | 0 | 0 | 35 | LTS-2724 |
A programmer, recreational runner and diver, live in the island of Bali, Indonesia. Programming in Java, Spring, Hibernate / JPA. You can support me working on this project, buy me a cup of coffee ☕ every little bit helps, thank you 🙏