【问题标题】:How do I programmatically determine operating system in Java?如何以编程方式确定 Java 中的操作系统?
【发布时间】:2010-09-18 17:07:21
【问题描述】:

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

【问题讨论】:

    标签: java operating-system


    【解决方案1】:

    你可以使用:

    System.getProperty("os.name")
    

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

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

    它所做的只是打印出 Java 实现提供的所有属性。它将让您了解可以通过属性找到有关 Java 环境的信息。 :-)

    【讨论】:

    【解决方案2】:

    十月。 2008:

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

    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 存在一个错误(在原始答案时不存在)。
    见“Java's “os.name” for Windows 10?

    【讨论】:

    • 我同意getOSName函数,基于OAOO(一次且仅一次);但是,考虑到哈希查找的速度,缓存是完全多余的。
    • 完全冗余可能有点苛刻,哈希查找比访问引用更昂贵。这一切都取决于上下文。
    • 好点...如果您认为这是一种不好的做法,请随意投反对票;)
    • 我重读了这个答案。如果要缓存,请缓存isWindowsisUnix 等的值。这样还可以节省字符串比较时间。
    • @Brian True。我已经相应地编辑了这个非常旧的答案,以参考更新的答案。
    【解决方案3】:

    如果您对开源项目如何执行此类操作感兴趣,可以在此处查看处理这些垃圾的 Terracotta 类 (Os.java):

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

    【讨论】:

    • 那个兵马俑课很全面!
    • 也遇到了 James Roper 在Wolfgang Fahl's answer 中指出的相同问题——使用toLowerCase 而不指定语言环境
    【解决方案4】:

    我发现OS Utils from Swingx 可以胜任。

    【讨论】:

    【解决方案5】:

    如其他答案所示,System.getProperty 提供原始数据。但是,Apache Commons Lang component 提供了具有方便属性的wrapper for java.lang.System,例如SystemUtils.IS_OS_WINDOWS,很像前面提到的 Swingx OS 实用程序。

    【讨论】:

    • 这真的很方便。您每天都会发现 Apache Lang3 的新功能!
    【解决方案6】:
    String osName = System.getProperty("os.name");
    System.out.println("Operating system " + osName);
    

    【讨论】:

      【解决方案7】:

      您尝试实现的一个小例子可能是类似于下面的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 中即可。

      【讨论】:

        【解决方案8】:

        以上答案中的某些链接似乎已损坏。我在下面的代码中添加了指向当前源代码的指针,并提供了一种使用枚举作为答案来处理检查的方法,以便在评估结果时可以使用 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;
          }
        }
        

        【讨论】:

        • (OS.indexOf("darwin") >= 0) 永远不可能为真,因为它在 (OS.indexOf("win") >= 0) 之后出现
        • 上面的代码可能存在语言环境问题,因为它使用了对语言环境敏感的 toLowerCase()。在将 i 转换为小写/大写时,这一点尤其重要,因为在土耳其,i 变为小写不带点 i (ı​​),而 i 变为大写带点 i (İ)。因此 "WINDOWS".toLowerCase().indexOf("win") 在土耳其将返回 -1。在对特定语言进行小写时始终传递区域设置,即 "WINDOWS".toLowerCase(Locale.ENGLISH).indexOf("win") 将在土耳其工作。
        • @JamesRoper -thanx 修复了这个问题。
        【解决方案9】:

        我喜欢 Wolfgang 的回答,只是因为我相信这样的事情应该是 consts...

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

        /**
         * 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 被返回。
        • 在我的原始答案中查看修复
        • 恭喜,你重新实现了 sun.awt.OSInfo#getOSType :)
        • HHHHH... 好一个... @Kirill Gamazkov 我当时没找到它.. 感谢您指出
        【解决方案10】:

        试试这个,简单易行

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

        【讨论】:

          【解决方案11】:

          此代码用于显示有关系统操作系统类型、名称、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));
              }
          }
          

          【讨论】:

            【解决方案12】:

            以下代码显示了您可以从 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
            \
            

            【讨论】:

              【解决方案13】:

              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 变量声明为静态,它只会消耗一次时间来识别系统类型,然后可以使用它直到您的应用程序停止。)

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

              就是这样!

              【讨论】:

              【解决方案14】:

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

              【讨论】:

              • 这应该是最好的答案!我只是在检查是否有人在这里提到过。
              • 有什么解决方法可以解决这个“受限 API”吗?我想尝试使用它,但它在 Eclipse 中给了我警告。我可以使用较旧的 jre(例如 jre1.8.0_171),但最新的 1.8 jres 将其标记为受限。
              • 不推荐使用整个“sun”包,我无法想象如何解决这个问题。似乎只是System.getProperty("os.name") 然后检查属性是否包含'Windows'、'Linux'、'Solaris'或'OS X',所以它与Vishal Chaudhari的回答基本相同
              【解决方案15】:

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

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

              例子:

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

              【讨论】:

              • 这个应该更高
              • 请注意,现在不鼓励访问“com/sun/javafx/*”(使用 JDK 1.8.0_121 检查)。
              • @MichaelMarton 你的陈述有参考吗?
              • @HummelingEngineeringBV:我想这是我的错误。我正在使用 eclipse Neon 4.6.3 并且“Java 构建路径”显示了几个“不鼓励:com/sun/javafx/**”警告。但是,正如我发现的那样,这恰好是一个 eclipse-bug 和/或 -feature(请参阅link)。
              • 我必须再纠正一次。从 Java 9/10+ 开始,几个“com.sun.*”包/API 即将被删除。查看this link 了解更多信息。我实际上偶然发现了这一点,因为我们使用了其中一些包。迁移到 eclipse 4.8/JDK 10,我们现在必须修复这些以及由于缺少引用而导致的其他几个编译器错误。
              【解决方案16】:

              我认为以下内容可以在更少的行中提供更广泛的覆盖范围

              import org.apache.commons.exec.OS;
              
              if (OS.isFamilyWindows()){
                              //load some property
                          }
              else if (OS.isFamilyUnix()){
                              //load some other property
                          }
              

              更多详情:https://commons.apache.org/proper/commons-exec/apidocs/org/apache/commons/exec/OS.html

              【讨论】:

                【解决方案17】:

                在 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>
                

                否则只需找到 j​​na 库 jar 文件(例如 jna-5.2.0.jar)并将其添加到类路径。

                【讨论】:

                  【解决方案18】:

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

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

                  或使用

                  boolean isWindows = OSInfo.getOSType().equals(OSInfo.OSType.WINDOWS);
                         if (isWindows){
                           // YOUR LOGIC HERE
                         }
                  

                  【讨论】:

                    【解决方案19】:

                    如果您在安全敏感的环境中工作,请仔细阅读此内容。

                    请不要相信通过System#getProperty(String) 子例程获得的属性!实际上,包括os.archos.nameos.version 在内的几乎所有属性都不像您所期望的那样是只读的——相反,它们实际上完全相反。

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

                    实际的问题是任何用户在运行有问题的JAR 时都可以编辑这些属性(通过-Dos.name=-Dos.arch= 等)。避免篡改应用程序参数的一种可能方法是查询RuntimeMXBean,如here 所示。下面的代码 sn-p 应该提供一些关于如何实现这一点的见解。

                    RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
                    List<String> 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
                        }
                    }
                    

                    【讨论】:

                    • File.separator 看起来不是一个严肃的解决方案。还有其他方法吗?
                    • 是的!实际上有一种非常优雅的方法可以检测系统属性的篡改。我会相应地更新答案。但请注意,检查只能做这么多 - 如果有人可以物理访问您的应用程序,则将有可能破坏它 - 无论检查多么复杂。
                    【解决方案20】:

                    热门答案的更短、更简洁(并且急切计算)的版本:

                    switch(OSType.DETECTED){
                    ...
                    }
                    

                    辅助枚举:

                    public enum OSType {
                        Windows, MacOS, Linux, Other;
                        public static final  OSType DETECTED;
                        static{
                            String OS = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH);
                            if ((OS.contains("mac")) || (OS.contains("darwin"))) {
                                DETECTED = OSType.MacOS;
                            } else if (OS.contains("win")) {
                                DETECTED = OSType.Windows;
                            } else if (OS.contains("nux")) {
                                DETECTED = OSType.Linux;
                            } else {
                                DETECTED = OSType.Other;
                            }
                        }
                    }
                    

                    【讨论】:

                      【解决方案21】:

                      由于 google 将“kotlin os name”指向此页面,因此这里是 @Memin 的 answer 的 Kotlin 版本:

                      private var _osType: OsTypes? = null
                      val osType: OsTypes
                          get() {
                              if (_osType == null) {
                                  _osType = with(System.getProperty("os.name").lowercase(Locale.getDefault())) {
                                      if (contains("win"))
                                          OsTypes.WINDOWS
                                      else if (listOf("nix", "nux", "aix").any { contains(it) })
                                          OsTypes.LINUX
                                      else if (contains("mac"))
                                          OsTypes.MAC
                                      else if (contains("sunos"))
                                          OsTypes.SOLARIS
                                      else
                                          OsTypes.OTHER
                                  }
                              }
                              return _osType!!
                          }
                      
                      enum class OsTypes {
                          WINDOWS, LINUX, MAC, SOLARIS, OTHER
                      }
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-06-29
                        • 2017-03-08
                        • 1970-01-01
                        • 2016-10-08
                        • 1970-01-01
                        相关资源
                        最近更新 更多