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

Posted

技术标签:

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

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

【问题讨论】:

【参考方案1】:

你可以使用:

System.getProperty("os.name")

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

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

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

【讨论】:

我正在使用Windows 10,但os.name 给了我Windows 8.1。这是为什么?这是哪里来的? nvm 发现 ***.com/questions/31909107/…【参考方案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):

http://svn.terracotta.org/svn/tc/dso/trunk/code/base/common/src/com/tc/util/runtime/ http://svn.terracotta.org/svn/tc/dso/tags/2.6.4/code/base/common/src/com/tc/util/runtime/

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

http://svn.terracotta.org/svn/tc/dso/trunk/common/src/main/java/com/tc/util/runtime/

【讨论】:

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

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

【讨论】:

上面的链接好像坏了,可能是SwingX引入了分支; 1.6 版本在这里:swingx.dev.java.net/source/browse/swingx/tags/SwingX-1-6/src/… @David Moles,谢谢。我回答时链接正常 - 我现在已经用你的链接更新了它。 最新版本在这里:java.net/projects/swingx/sources/svn/content/trunk/swingx-core/… Oracle 关闭了 java.net 站点,所以关心的人应该编辑这个答案来修复链接。 我在这里找到了一个版本github.com/tmyroadctfig/swingx/blob/master/swingx-common/src/… - 感谢@MarkHu 通知断开的链接【参考方案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://***.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://***.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:

就是这样!

【讨论】:

我想在开源项目中使用这段代码(github.com/openhab/openhab-addons),你可以吗? 是的,请随意使用。【参考方案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

【讨论】:

以上是关于如何以编程方式确定 Java 中的操作系统?的主要内容,如果未能解决你的问题,请参考以下文章

Zapier:如何以动态/编程方式选择帐户

在 Windows 中以编程方式确定电源使用情况?

如何以编程方式确定哪些 SQL 表具有标识列

如何以编程方式确定 PHP 中的文档根目录?

如何以编程方式确定系统设备声音设置?

如何以编程方式关闭 Android 中的共享系统对话框?