如何以编程方式确定Java的操作系统?


526

我想确定Java程序正在以编程方式运行的主机的操作系统(例如:我希望能够基于我在Windows还是Unix平台上加载不同的属性)。做到100%可靠性的最安全方法是什么?

Answers:


617

您可以使用:

System.getProperty("os.name")

PS:您可能会发现此代码有用:

class ShowProperties {
    public static void main(String[] args) {
        System.getProperties().list(System.out);
    }
}

它所做的只是打印出Java实现提供的所有属性。通过它,您可以了解可以通过属性了解Java环境的内容。:-)


6
我正在使用Windows 10os.name却给了我Windows 8.1。这是为什么?这是哪里来的?
布赖恩



82

2008年10月:

我建议将其缓存在静态变量中:

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
}

这样,每次请求Os时,在应用程序的生存期内就不会多次获取该属性。


2016年2月:7年后:

Windows 10有一个错误(原始答案时不存在)。
请参阅“ Windows 10的Java的“ os.name”?


5
我同意基于OAOO的getOSName函数(一次且仅一次);但是,考虑到散列查找的速度,缓存完全是多余的。
克里斯·杰斯特·杨

6
完全冗余可能有点苛刻,哈希查找比访问引用更昂贵。这完全取决于上下文。
日克雷格纪念日

2
好点...如果您认为这是不好的做法,请随意投票;)
VonC

5
我重读了这个答案。如果你要缓存,缓存的值isWindowsisUnix等等。这样,您可以节省字符串比较时也。
克里斯·杰斯特·杨

2
@Brian True。我已经相应地编辑了这个非常老的答案,以引用最新的答案。
VonC

44

以上答案中的某些链接似乎已断开。我在下面的代码中添加了指向当前源代码的指针,并提供了一种使用枚举作为答案来处理检查的方法,以便在评估结果时可以使用switch语句:

OsCheck.OSType ostype=OsCheck.getOperatingSystemType();
switch (ostype) {
    case Windows: break;
    case MacOS: break;
    case Linux: break;
    case Other: break;
}

助手类是:

/**
 * 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;
  }
}

3
(OS.indexOf(“ darwin”)> = 0)永远不会是真实的,因为它是在(OS.indexOf(“ win”)> = 0)之后出现的
威廉

14
上面的代码可能会出现语言环境问题,因为它使用了对语言环境敏感的toLowerCase()。在将i转换为小写/大写字母时,这尤其重要,因为在土耳其,我变成了小写的点划线i(ı),而我变成了大写的点缀i(İ)。因此,“ WINDOWS” .toLowerCase()。indexOf(“ win”)在土耳其将返回-1。在使用特定语言的小写字母时,请始终传递语言环境,例如“ WINDOWS” .toLowerCase(Locale.ENGLISH).indexOf(“ win”)在土耳其可以使用。
詹姆斯·罗珀

@JamesRoper-thanx修复了此问题。
Wolfgang Fahl 2014年

7
OS.contains(...)
Grigory Kislin,2015年

42

以下JavaFX类具有确定当前操作系统的静态方法(isWindows(),isLinux()...):

  • com.sun.javafx.PlatformUtil
  • com.sun.media.jfxmediaimpl.HostUtils
  • com.sun.javafx.util.Utils

例:

if (PlatformUtil.isWindows()){
           ...
}

这应该更高
栖息地

3
请注意,现在不建议访问“ com / sun / javafx / *”(已通过JDK 1.8.0_121进行了检查)。
迈克尔·马顿

1
@MichaelMarton有您的陈述的参考吗?
Hummeling Engineering BV

@HummelingEngineeringBV:我想这是我的错误。我正在使用Eclipse Neon 4.6.3,“ Java Build Path”显示了几个“ Discouraged:com / sun / javafx / **”警告。但是,正如我发现的那样,这恰好是eclipse-bug和/或-feature(请参阅link)。
Michael Marton '18年

2
我必须再纠正自己一次。从Java 9/10 +开始,将删除几个“ com.sun。*”软件包/ API。查看此链接以获取更多信息。我实际上偶然发现了这一点,因为我们使用了其中一些软件包。迁移到Eclipse 4.8 / JDK 10之后,我们现在必须修复由于缺少引用而导致的这些错误以及其他一些编译器错误。
Michael Marton '18

16

TL; DR

要访问操作系统,请使用:System.getProperty("os.name")


但是为什么不创建一个实用程序类,使其可重用呢!而且在多个呼叫上可能要快得多。干净,清晰,更快!

为此类实用程序功能创建一个Util类。然后为每种操作系统类型创建公共枚举。

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;
    }
}

现在,您可以按如下所示轻松地从任何类中调用类(PS:由于我们将os变量声明为static,所以它只消耗一次时间来标识系统类型,然后可以使用它直到您的应用程序停止为止。)

            switch (Util.getOS()) {
            case WINDOWS:
                //do windows stuff
                break;
            case LINUX:

就是这样!


2
我想在一个开源项目(github.com/openhab/openhab-addons)中使用这段代码,你可以吗?
Consti P

是的,请随时使用它。
Memin

13

您要实现的目标的一个小示例可能class与下面的示例类似:

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");
    }
}

这种特定的实现是非常可靠的,应该是普遍适用的。只需将其复制并粘贴到您class的选择中即可。


10

如果您对开源项目的工作方式感兴趣,可以在此处查看处理此垃圾的Terracotta类(Os.java):

您可以在此处看到类似的类来处理JVM版本(Vm.java和VmVersion.java):


2
兵马俑课非常全面!
斯图尔特

3
当心许可证!!
harschware,2015年

詹姆斯·罗珀(James Roper)在沃尔夫冈·法尔(Wolfgang Fahl)的答案中也指出了同样的问题-使用toLowerCase不指定语言环境
kbolino

9

试试这个,简单又容易

System.getProperty("os.name");
System.getProperty("os.version");
System.getProperty("os.arch");

9

取自该项目https://github.com/RishiGupta12/serial-communication-manager

String osName = System.getProperty("os.name");
String osNameMatch = osName.toLowerCase();
if(osNameMatch.contains("linux")) {
    osType = OS_LINUX;
}else if(osNameMatch.contains("windows")) {
    osType = OS_WINDOWS;
}else if(osNameMatch.contains("solaris") || osNameMatch.contains("sunos")) {
    osType = OS_SOLARIS;
}else if(osNameMatch.contains("mac os") || osNameMatch.contains("macos") || osNameMatch.contains("darwin")) {
    osType = OS_MAC_OS_X;
}else {
}

8

下面的代码显示了您可以从System API获得的值,以及可以通过此API获得的所有这些信息。

public class App {
    public static void main( String[] args ) {
        //Operating system name
        System.out.println(System.getProperty("os.name"));

        //Operating system version
        System.out.println(System.getProperty("os.version"));

        //Path separator character used in java.class.path
        System.out.println(System.getProperty("path.separator"));

        //User working directory
        System.out.println(System.getProperty("user.dir"));

        //User home directory
        System.out.println(System.getProperty("user.home"));

        //User account name
        System.out.println(System.getProperty("user.name"));

        //Operating system architecture
        System.out.println(System.getProperty("os.arch"));

        //Sequence used by operating system to separate lines in text files
        System.out.println(System.getProperty("line.separator"));

        System.out.println(System.getProperty("java.version")); //JRE version number

        System.out.println(System.getProperty("java.vendor.url")); //JRE vendor URL

        System.out.println(System.getProperty("java.vendor")); //JRE vendor name

        System.out.println(System.getProperty("java.home")); //Installation directory for Java Runtime Environment (JRE)

        System.out.println(System.getProperty("java.class.path"));

        System.out.println(System.getProperty("file.separator"));
    }
}

答案:-

Windows 7
6.1
;
C:\Users\user\Documents\workspace-eclipse\JavaExample
C:\Users\user
user
amd64


1.7.0_71
http://java.oracle.com/
Oracle Corporation
C:\Program Files\Java\jre7
C:\Users\user\Documents\workspace-Eclipse\JavaExample\target\classes
\

7

我发现SwingxOS Utils可以完成这项工作。


2
上面的链接似乎已断开,可能是由于SwingX引入了分支;1.6版本是在这里:swingx.dev.java.net/source/browse/swingx/tags/SwingX-1-6/src/...
戴维·莫尔斯

1
@David Moles,谢谢。我回答时该链接正常-我已经用您的链接更新了。
理查德·哈里森




4

您可以只使用sun.awt.OSInfo#getOSType()方法


这应该是最好的答案!我只是在检查是否有人已经在这里提到过这一点。
MartinKrajčírovič18年

有什么变通办法是“受限制的API”吗?我想尝试使用它,但是它在Eclipse中给了我警告。我可以使用较旧的jre(例如jre1.8.0_171),但是最新的1.8 jre将其标记为受限。
Brian_Entei

4

如果您在安全敏感的环境中工作,请通读此文。

请不要信任通过System#getProperty(String)子例程获得的财产!事实上,几乎所有的财产,包括os.archos.name,和os.version都不像您期望的那样是只读的-相反,它们实际上是相反的。

首先,任何具有足够权限调用System#setProperty(String, String)子例程的代码都可以随意修改返回的文字。但是,这并不一定是这里的主要问题,因为可以通过使用所谓的来解决SecurityManager,如这里更详细地描述。

实际的问题是,运行JAR问题时,任何用户都可以编辑这些属性。这意味着无法确定这些属性是否确实准确。因此,这里有一些其他的检查来尝试避免篡改:

// The first thing we're able to do is to query the filesystem.
switch (java.io.File.separator)
{
    case "/":
        // Windows is a potential candidate.
        break;
    case "\\":
        // And here it could really be anything else.
        break;
    default:
        // There's probably something really wrong here by now.
        break;
}

另一个好主意是检查操作系统特定目录的存在。无论采用哪种方法,请记住,Java语言被认为是跨平台的。那么,为什么不尝试这样做呢?


3

我喜欢沃尔夫冈的答案,只是因为我相信这样的事情应该是常量。

所以我为自己改了一下,并想分享它:)

/**
 * types of Operating Systems
 *
 * please keep the note below as a pseudo-license
 *
 * helper class to check the operating system this Java VM runs in
 * 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
 */
public enum OSType {
    MacOS("mac", "darwin"),
    Windows("win"),
    Linux("nux"),
    Other("generic");

    private static OSType detectedOS;

    private final String[] keys;

    private OSType(String... keys) {
        this.keys = keys;
    }

    private boolean match(String osKey) {
        for (int i = 0; i < keys.length; i++) {
            if (osKey.indexOf(keys[i]) != -1)
                return true;
        }
        return false;
    }

    public static OSType getOS_Type() {
        if (detectedOS == null)
            detectedOS = getOperatingSystemType(System.getProperty("os.name", Other.keys[0]).toLowerCase());
        return detectedOS;
    }

    private static OSType getOperatingSystemType(String osKey) {
        for (OSType osType : values()) {
            if (osType.match(osKey))
                return osType;
        }
        return Other;
    }
}

似乎“ darwin”永远无法匹配,因为选中“ win”将已经导致Windows返回。
tvkanters 2014年

看到我的原始答案中的解决方法
Wolfgang Fahl 2014年

3
恭喜,您已经重新实现了sun.awt.OSInfo#getOSType :)
Kirill Gamazkov,2016年

HHHHH ...好人... @ Kirill Gamazkov我当时没找到..谢谢你指出来
TacB0sS 18-4-27

2

此代码用于显示有关系统os类型,名称,java信息等的所有信息。

public static void main(String[] args) {
    // TODO Auto-generated method stub
    Properties pro = System.getProperties();
    for(Object obj : pro.keySet()){
        System.out.println(" System  "+(String)obj+"     :  "+System.getProperty((String)obj));
    }
}

1

在com.sun.jna.Platform类中,您可以找到有用的静态方法,例如

Platform.isWindows();
Platform.is64Bit();
Platform.isIntel();
Platform.isARM();

以及更多。

如果您使用Maven,只需添加依赖项

<dependency>
 <groupId>net.java.dev.jna</groupId>
 <artifactId>jna</artifactId>
 <version>5.2.0</version>
</dependency>

否则,只需找到jna库jar文件(例如jna-5.2.0.jar)并将其添加到classpath中即可。


1

只需使用com.sun.javafx.util.Utils如下。

if ( Utils.isWindows()){
     // LOGIC HERE
}

或使用

boolean isWindows = OSInfo.getOSType().equals(OSInfo.OSType.WINDOWS);
       if (isWindows){
         // YOUR LOGIC HERE
       }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.