Wie bestimme ich programmgesteuert das Betriebssystem in Java?

526

Ich möchte das Betriebssystem des Hosts ermitteln, auf dem mein Java-Programm programmgesteuert ausgeführt wird (zum Beispiel: Ich möchte verschiedene Eigenschaften laden können, je nachdem, ob ich mich auf einer Windows- oder einer Unix-Plattform befinde). Was ist der sicherste Weg, dies mit 100% iger Zuverlässigkeit zu tun?

karlgrz
quelle

Antworten:

617

Sie können verwenden:

System.getProperty("os.name")

PS Sie können diesen Code nützlich finden:

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

Sie drucken lediglich alle Eigenschaften Ihrer Java-Implementierungen aus. Sie erhalten eine Vorstellung davon, was Sie über Eigenschaften über Ihre Java-Umgebung erfahren können. :-)

Chris Jester-Young
quelle
6
Ich benutze Windows 10und os.namegebe mir doch Windows 8.1. Warum ist das so? Woher kommt das?
Brian
82

Okt. 2008:

Ich würde empfehlen, es in einer statischen Variablen zwischenzuspeichern:

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
}

Auf diese Weise rufen Sie die Eigenschaft jedes Mal, wenn Sie nach den Os fragen, nicht mehr als einmal in der Lebensdauer Ihrer Anwendung ab.


Februar 2016: 7+ Jahre später:

Es gibt einen Fehler mit Windows 10 (der zum Zeitpunkt der ursprünglichen Antwort nicht vorhanden war).
Siehe " Javas" os.name "für Windows 10? "

VonC
quelle
5
Ich stimme der Funktion getOSName auf der Basis von OAOO zu (einmal und nur einmal). Das Caching ist jedoch angesichts der Geschwindigkeit der Hash-Suche völlig redundant.
Chris Jester-Young
6
Völlig redundant kann etwas hart sein, Hash-Lookups sind teurer als der Zugriff auf eine Referenz. Es hängt alles vom Kontext ab.
Craig Day
2
Gute Punkte ... Fühlen Sie sich frei, abzustimmen, wenn Sie denken, dass es eine schlechte Praxis ist;)
VonC
5
Ich habe diese Antwort noch einmal gelesen. Wenn Sie Cache werden, zwischenspeichern die Werte isWindows, isUnixusw. Auf diese Weise können speichern auf der Saite Vergleichszeit auch.
Chris Jester-Young
2
@ Brian True. Ich habe diese sehr alte Antwort entsprechend bearbeitet, um auf die neuere zu verweisen.
VonC
44

Einige der Links in den obigen Antworten scheinen defekt zu sein. Ich habe im folgenden Code Zeiger auf den aktuellen Quellcode hinzugefügt und biete einen Ansatz für die Behandlung der Prüfung mit einer Aufzählung als Antwort an, damit bei der Auswertung des Ergebnisses eine switch-Anweisung verwendet werden kann:

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

Die Helferklasse ist:

/**
 * 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;
  }
}
Wolfgang Fahl
quelle
3
(OS.indexOf ("darwin")> = 0) kann niemals wahr sein, weil es nach (OS.indexOf ("win")> = 0)
William
14
Der obige Code kann Probleme mit dem Gebietsschema haben, da er toLowerCase () verwendet, das für das Gebietsschema empfindlich ist. Dies ist besonders wichtig, wenn ich i in Klein- / Großbuchstaben umwandle, da ich in der Türkei in Kleinbuchstaben undot (i) und in Großbuchstaben in i (İ) werde. "WINDOWS" .toLowerCase (). IndexOf ("win") gibt also in der Türkei -1 zurück. Übergeben Sie immer ein Gebietsschema, wenn Sie eine bestimmte Sprache in Kleinbuchstaben schreiben, dh "WINDOWS" .toLowerCase (Locale.ENGLISH) .indexOf ("win") funktioniert in der Türkei.
James Roper
@ JamesRoper - Danke, das wurde behoben.
Wolfgang Fahl
7
OS.contains (...)
Grigory Kislin
42

Die folgenden JavaFX-Klassen verfügen über statische Methoden zum Ermitteln des aktuellen Betriebssystems (isWindows (), isLinux () ...):

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

Beispiel:

if (PlatformUtil.isWindows()){
           ...
}
Igor Rybak
quelle
Dies sollte höher sein
Lebensräume
3
Bitte beachten Sie, dass der Zugriff auf "com / sun / javafx / *" jetzt nicht empfohlen wird (dies wurde mit JDK 1.8.0_121 überprüft).
Michael Marton
1
@MichaelMarton Haben Sie eine Referenz für Ihre Aussage?
Hummeling Engineering BV
@HummelingEngineeringBV: Ich denke, es war ein Fehler von meiner Seite. Ich arbeite mit Eclipse Neon 4.6.3 und der "Java Build Path" zeigt mehrere "Discouraged: com / sun / javafx / **" -Warnungen. Wie ich jedoch herausgefunden habe, handelt es sich um einen Eclipse-Fehler und / oder eine Eclipse-Funktion (siehe Link ).
Michael Marton
2
Ich muss mich noch einmal korrigieren. Ab Java 9/10 + werden mehrere "com.sun. *" - Pakete / APIs entfernt. Überprüfen Sie diesen Link für weitere Informationen. Ich bin tatsächlich darüber gestolpert, weil wir einige dieser Pakete verwenden. Bei der Migration auf Eclipse 4.8 / JDK 10 müssen diese und einige andere Compilerfehler aufgrund fehlender Referenzen behoben werden.
Michael Marton
16

TL; DR

Für den Zugriff auf das Betriebssystem verwenden Sie : System.getProperty("os.name").


Aber warum nicht eine Utility-Klasse erstellen, sie wiederverwendbar machen? Und wahrscheinlich viel schneller bei mehreren Anrufen. Sauber, klar, schneller!

Erstellen Sie eine Util-Klasse für solche Utility-Funktionen. Erstellen Sie dann öffentliche Aufzählungen für jeden Betriebssystemtyp.

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

Jetzt können Sie die Klasse von jeder Klasse aus wie folgt aufrufen: (PS Da wir die Variable os als statisch deklariert haben, benötigt sie nur einmal Zeit, um den Systemtyp zu identifizieren, und kann dann verwendet werden, bis Ihre Anwendung angehalten wird.)

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

und das ist alles!

Memin
quelle
2
Ich möchte diesen Code in einem Open-Source-Projekt ( github.com/openhab/openhab-addons ) verwenden. Ist das für Sie in Ordnung?
Consti P
Ja, bitte zögern Sie nicht, es zu benutzen.
Memin
13

Ein kleines Beispiel für das, was Sie erreichen möchten, classähnelt wahrscheinlich dem, was darunter liegt:

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

Diese spezielle Implementierung ist sehr zuverlässig und sollte universell anwendbar sein. Kopieren Sie es einfach und fügen Sie es in das Ihrer classWahl ein.

Nikesh Jauhari
quelle
10

Wenn Sie daran interessiert sind, wie ein Open Source-Projekt solche Dinge macht, können Sie sich hier die Terracotta-Klasse (Os.java) ansehen, die diesen Müll behandelt:

Eine ähnliche Klasse für JVM-Versionen (Vm.java und VmVersion.java) finden Sie hier:

Alex Miller
quelle
2
Diese Terrakotta-Klasse ist ziemlich umfassend!
Stewart
3
Vorsicht vor der Lizenz !!
Harschware
leidet auch unter dem gleichen Problem, das James Roper in Wolfgang Fahls Antwort identifiziert hat - Verwendung toLowerCaseohne Angabe eines Gebietsschemas
kbolino
9

Versuchen Sie dies einfach und unkompliziert

System.getProperty("os.name");
System.getProperty("os.version");
System.getProperty("os.arch");
Kamidu
quelle
9

Entnommen aus diesem Projekt 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 {
}
John Miller
quelle
8

Der folgende Code zeigt die Werte, die Sie von der System-API erhalten können. Dies sind alles Dinge, die Sie über diese API erhalten können.

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

Antworten: -

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
\
Ash_P
quelle
7

Ich finde, dass die OS Utils von Swingx den Job machen.

Richard Harrison
quelle
2
Der obige Link scheint unterbrochen zu sein, wahrscheinlich weil SwingX Zweige einführt. Die Version 1.6 ist hier: Swingx.dev.java.net/source/browse/swingx/tags/SwingX-1-6/src/…
David Moles
1
@ David Moles, danke. Der Link war in Ordnung, als ich antwortete. Ich habe ihn jetzt mit Ihrem aktualisiert.
Richard Harrison
2
Die neueste Version ist hier: java.net/projects/swingx/sources/svn/content/trunk/swingx-core/…
Vladislav Rastrusny
5
String osName = System.getProperty("os.name");
System.out.println("Operating system " + osName);
Vishal Chaudhari
quelle
4

Sie können einfach die Methode sun.awt.OSInfo # getOSType () verwenden

Kirill Gamazkov
quelle
Dies sollte die beste Antwort sein! Ich habe nur nachgesehen, ob dies hier schon jemand erwähnt hat.
Martin Krajčírovič
Gibt es eine Problemumgehung für diese "eingeschränkte API"? Ich würde gerne versuchen, dies zu verwenden, aber es gibt mir diese Warnung in Eclipse. Ich kann ein älteres jre verwenden (z. B. jre1.8.0_171), aber die neuesten 1.8 jres haben es als eingeschränkt markiert.
Brian_Entei
4

Wenn Sie in einer sicherheitsrelevanten Umgebung arbeiten, lesen Sie dies bitte durch.

Bitte vertrauen Sie niemals einer Eigenschaft, die Sie über das System#getProperty(String)Unterprogramm erhalten haben! Eigentlich fast jedes Eigentum , einschließlich os.arch, os.nameund os.versionist nicht nur lesbar , wie Sie vielleicht erwarten würde - stattdessen sind sie eigentlich ganz im Gegenteil.

Zunächst kann jeder Code mit ausreichender Berechtigung zum Aufrufen der System#setProperty(String, String)Unterroutine das zurückgegebene Literal nach Belieben ändern. Dies ist hier jedoch nicht unbedingt das Hauptproblem, da es durch die Verwendung eines so genannten Problems gelöst werden kann SecurityManager, wie hier ausführlicher beschrieben .

Das eigentliche Problem ist, dass jeder Benutzer diese Eigenschaften bearbeiten kann, wenn er die JARbetreffende Funktion ausführt. Dies bedeutet, dass es keine Möglichkeit gibt , festzustellen, ob diese Eigenschaften tatsächlich korrekt sind. Aus diesem Grund finden Sie hier einige zusätzliche Überprüfungen, um Manipulationen zu vermeiden:

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

Eine weitere gute Idee ist es, das Vorhandensein betriebssystemspezifischer Verzeichnisse zu überprüfen. Denken Sie bei jedem Ansatz daran, dass die Java- Sprache als plattformübergreifende Einheit eingerückt ist. Warum versuchst du nicht das Gleiche zu tun?

Niklas Simandi
quelle
3

Ich mochte Wolfgangs Antwort, nur weil ich glaube, dass solche Dinge Konstanten sein sollten ...

Also habe ich es ein bisschen für mich selbst umformuliert und dachte, es zu teilen :)

/**
 * 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
quelle
Es scheint, dass "darwin" niemals verglichen werden kann, da das Aktivieren von "win" bereits dazu führen würde, dass Windows zurückgegeben wird.
tvkanters
siehe Fix in meiner ursprünglichen Antwort
Wolfgang Fahl
3
Herzlichen Glückwunsch, Sie haben sun.awt.OSInfo # getOSType neu implementiert :)
Kirill Gamazkov
HHHHH ... gut ... @Kirill Gamazkov Ich habe es damals nicht gefunden ... danke für den Hinweis
TacB0sS
2

Dieser Code zum Anzeigen aller Informationen über den Betriebssystem-Betriebssystemtyp, den Namen, Java-Informationen usw.

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
quelle
1

In der Klasse com.sun.jna.Platform finden Sie nützliche statische Methoden wie

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

und vieles mehr.

Wenn Sie Maven verwenden, fügen Sie einfach die Abhängigkeit hinzu

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

Andernfalls suchen Sie einfach die JNA-Bibliotheks-JAR-Datei (z. B. jna-5.2.0.jar) und fügen Sie sie dem Klassenpfad hinzu.

Vladimir Vaschenko
quelle
1

Verwenden Sie einfach com.sun.javafx.util.Utilswie unten.

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

ODER VERWENDUNG

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