Как программно определить операционную систему на Java?

526

Я хотел бы определить операционную систему хоста, на котором моя Java-программа выполняется программно (например: я хотел бы иметь возможность загружать различные свойства в зависимости от того, нахожусь ли я на платформе Windows или Unix). Какой самый безопасный способ сделать это со 100% надежностью?

karlgrz
источник

Ответы:

617

Ты можешь использовать:

System.getProperty("os.name")

PS Вы можете найти этот код полезным:

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

Все, что он делает, это распечатывает все свойства, предоставляемые вашими реализациями Java. Это даст вам представление о том, что вы можете узнать о вашей среде Java через свойства. :-)

Крис Шут-Янг
источник
6
Я использую Windows 10и все же os.nameотдает мне Windows 8.1. Это почему? Откуда это?
Брайан
9
NVM нашел stackoverflow.com/questions/31909107/…
Брайан
152

Как указано в других ответах, System.getProperty предоставляет необработанные данные. Тем не менее, компонент Apache Commons Lang предоставляет оболочку для java.lang.System с удобными свойствами SystemUtils.IS_OS_WINDOWS, похожими на вышеупомянутую утилиту Swingx OS.

Лейф Карлсен
источник
2
Это действительно удобно. Вы открываете новые возможности в Apache Lang3 каждый день!
Робин Йонссон
82

Октябрь 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 года: 7+ лет спустя:

В Windows 10 есть ошибка (которой не было на момент первоначального ответа).
Смотрите " Java os.name" для Windows 10? "

VonC
источник
5
Я согласен с функцией getOSName, на основе OAOO (один раз и только один раз); однако, кеширование полностью избыточно, учитывая скорость поиска хешей.
Крис Джестер-Янг
6
Полностью избыточный может быть немного грубоватым, поиск хеша дороже, чем доступ к ссылке. Все зависит от контекста.
День Крейга
2
Хорошие моменты ... Не стесняйтесь понижать голоса, если считаете, что это плохая практика;)
VonC
5
Я перечитал этот ответ. Если вы собираетесь в кэш, кэш значения isWindows, isUnixи т.д. Таким образом , вы сэкономите на время сравнения строк тоже.
Крис Шестер-Янг
2
@ Брайан Правда. Я соответственно отредактировал этот очень старый ответ, чтобы сослаться на более новый.
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 становится прописной буквой i (İ). Таким образом, "WINDOWS" .toLowerCase (). IndexOf ("win") вернет -1 в Турции. Всегда передавайте языковой стандарт при выполнении строчных букв для определенного языка, например «WINDOWS» .toLowerCase (Locale.ENGLISH) .indexOf («win») будет работать в Турции.
Джеймс Ропер
@JamesRoper - спасибо, это исправлено.
Вольфганг Фахл
7
OS.contains (...)
Григорий Кислин
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» показывает несколько предупреждений: «Не рекомендуется: com / sun / javafx / **». Однако, как я выяснил, это ошибка-затмение и / или -функция (см. Ссылку ).
Майкл Мартон
2
Я должен исправить себя еще раз. Начиная с Java 9/10, несколько пакетов / API "com.sun. *" Будут удалены. Проверьте эту ссылку для получения дополнительной информации. Я действительно наткнулся на это, потому что мы используем некоторые из этих пакетов. Переходя на затмение 4.8 / JDK 10, теперь мы должны исправить эти и некоторые другие ошибки компилятора из-за отсутствия ссылок.
Майкл Мартон
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 как статическую, она потребует времени только один раз для определения типа системы, затем она может использоваться до тех пор, пока ваше приложение не остановится.)

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

и это все!

Memin
источник
2
Я хочу использовать этот фрагмент кода в проекте с открытым исходным кодом ( github.com/openhab/openhab-addons ), с вами все в порядке?
Consti P
Да, пожалуйста, не стесняйтесь использовать его.
Мемин
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
также страдает от той же проблемы, выявленной Джеймсом Ропером в ответе Вольфганга Фала - использование toLowerCaseбез указания локали
kbolino
9

Попробуйте это, просто и легко

System.getProperty("os.name");
System.getProperty("os.version");
System.getProperty("os.arch");
Kamidu
источник
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

В приведенном ниже коде показаны значения, которые вы можете получить из системного 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
\
Pra_A
источник
7

Я считаю, что ОС Utils от Swingx делает свою работу.

Ричард Харрисон
источник
2
Ссылка выше, кажется, не работает, возможно, из-за веток SwingX; версия 1.6 находится здесь: swingx.dev.java.net/source/browse/swingx/tags/SwingX-1-6/src/…
Дэвид
1
@ Дэвид Моулз, спасибо. Ссылка была в порядке, когда я ответил - я теперь обновил его с вашим.
Ричард Харрисон
2
Последняя версия находится здесь: java.net/projects/swingx/sources/svn/content/trunk/swingx-core/…
Владислав Раструсный
5
String osName = System.getProperty("os.name");
System.out.println("Operating system " + osName);
Вишал Чаудхари
источник
4

Вы можете просто использовать sun.awt.OSInfo # getOSType () метод

Кирилл Гамазков
источник
Это должен быть лучший ответ! Я просто проверял, упомянул ли кто-то это здесь.
Мартин Крайчирович
Любой обходной путь для того, чтобы быть «ограниченным API»? Я хотел бы попытаться использовать это, но это дает мне это предупреждение в Eclipse. Я могу использовать более старую версию jre (например, jre1.8.0_171), но в последних 1.8 jre она помечена как ограниченная.
Brian_Entei
4

Если вы работаете в среде, чувствительной к безопасности, пожалуйста, прочитайте это до конца.

Пожалуйста, воздержитесь от доверия к собственности, полученной с помощью System#getProperty(String)подпрограммы! На самом деле, почти все свойства, включая os.arch, os.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;
    }
}
TacB0sS
источник
Кажется, что «Дарвин» никогда не может быть сопоставлен, потому что проверка «победа» уже приведет к возврату Windows.
твкантер
см. исправление в моем первоначальном ответе
Вольфганг Фаль
3
Поздравляю, вы переопределили sun.awt.OSInfo # getOSType :)
Кирилл Гамазков
ХХХХХ ... хороший ... @ Кирилл Гамазков Я тогда не нашел его ... спасибо, что указал на это
TacB0sS
2

Этот код для отображения всей информации о типе ОС, имени, информации о 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));
    }
}
ShinnedHawks
источник
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>

В противном случае просто найдите jar-файл библиотеки jna (например, 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
       }
ITRO
источник