Як я можу програмно визначити операційну систему на Java?


526

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

Відповіді:


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. Чому так? Звідки це походить?
Брайан


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
}

Таким чином, кожен раз, коли ви запитуєте про ОС, ви не отримуєте майно більше одного разу за життя вашої програми.


Лютий 2016: Через 7 років:

Існує помилка з Windows 10 (яка не існувала на момент оригінальної відповіді).
Див . "Ось.ім'я " Java для Windows 10? "


5
Я погоджуюся з функцією getOSName на основі OAOO (один раз і єдиний раз); однак кешування є абсолютно зайвим, враховуючи швидкість пошуку хешу.
Кріс Єстер-Янг

6
Повністю зайві можуть бути суворими, пошук хешів коштує дорожче, ніж доступ до посилання. Все залежить від контексту.
День Крейга

2
Хороші бали ... Не соромтеся брати участь у голосуванні, якщо ви вважаєте, що це погана практика;)
VonC

5
Я перечитав цю відповідь. Якщо ви збираєтеся в кеш, кеш значення isWindows, isUnixі т.д. Таким чином , ви заощадите на час порівняння рядків теж.
Кріс Єстер-Янг

2
@Brian True. Відповідно я відредагував цю дуже стару відповідь, щоб посилатися на більш пізню.
VonC

44

деякі посилання у відповідях вище, здається, порушені. Я додав покажчики до поточного вихідного коду в наведеному нижче коді і пропоную підхід для обробки чека з перерахунком як відповідь, щоб оператор перемикання міг бути використаний при оцінці результату:

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)
William

14
У наведеному вище коді можуть виникнути проблеми з локальною локальністю, оскільки він використовує toLowerCase (), який чутливий до мови. Де це особливо важливо при перетворенні 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: Я думаю, це була помилка з мого боку. Я працюю з затемненням Neon 4.6.3, і "Шлях збірки Java" показує кілька попереджень "Discuraged: 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 Оскільки ми оголосили змінну ос як статичну, вона буде витрачати час лише один раз для ідентифікації типу системи, то її можна використовувати, поки ваша програма не зупиниться.)

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

і це все!


2
Я хочу використовувати цей фрагмент коду у проекті з відкритим кодом ( github.com/openhab/openhab-addons ), чи з вами це нормально?
Консті П

Так, будь ласка, не соромтесь ним користуватися.
Мемін

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
остерігайтеся ліцензії !!
гарнітур

також страждає від того ж питання, яке визначив Джеймс Ропер у відповіді Вольфганга Фаля - використання 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

Нижче в коді показані значення, які можна отримати із системного 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

Я вважаю, що Utils OS від Swingx виконує цю роботу.


2
Наведене вище посилання начебто порушено, ймовірно, через впровадження SwingX гілок; випуск 1.6 тут: swingx.dev.java.net/source/browse/swingx/tags/SwingX-1-6/src/…
Девід

1
@David Moles, дякую. Коли я відповів, посилання було нормально - я тепер оновив його з вашим.
Річард Гаррісон




4

Можна просто використовувати метод sun.awt.OSInfo # getOSType ()


Це має бути найкращою відповіддю! Я просто перевіряв, чи хтось уже згадував це тут.
Martin Krajčírovič

Будь-яке рішення щодо цього "обмеженого API"? Я хотів би спробувати використовувати це, але це дає мені це попередження у Eclipse. Я можу використовувати старіший jre (наприклад, jre1.8.0_171), але в останніх 1,8 jres він позначений як обмежений.
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

Мені сподобалась відповідь Вольфганга, просто тому, що я вважаю, що такі речі повинні бути 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;
    }
}

Здається, що "дарвін" ніколи не може бути зіставлений, оскільки перевірка "виграти" вже призведе до повернення Windows.
tvkanters

див. виправлення в моїй оригінальній відповіді
Вольфганг Фаль

3
Вітаємо, ти повторно доповнив sun.awt.OSInfo # getOSType :)
Кирило Гамазков

HHHHH ... хороший ... @ Кірілл Гамазков я тоді його не знайшов .. дякую, що вказав на це
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));
    }
}

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
       }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.