Come posso determinare a livello di codice il sistema operativo in Java?


526

Vorrei determinare il sistema operativo dell'host che il mio programma Java è in esecuzione a livello di codice (ad esempio: vorrei essere in grado di caricare proprietà diverse in base al fatto che io sia su una piattaforma Windows o Unix). Qual è il modo più sicuro per farlo con affidabilità al 100%?

Risposte:


617

Puoi usare:

System.getProperty("os.name")

PS Potresti trovare utile questo codice:

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

Tutto ciò che fa è stampare tutte le proprietà fornite dalle implementazioni Java. Ti darà un'idea di cosa puoi scoprire sul tuo ambiente Java tramite le proprietà. :-)


6
Sto usando Windows 10e os.namemi dà ancora Windows 8.1. Perché? Da dove viene questo?
Brian,



82

Ottobre 2008:

Consiglierei di memorizzarlo nella cache in una variabile statica:

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
}

In questo modo, ogni volta che chiedi l'OS, non recuperi la proprietà più di una volta nella vita della tua applicazione.


Febbraio 2016: oltre 7 anni:

C'è un bug con Windows 10 (che non esisteva al momento della risposta originale).
Vedi " Java" os.name "per Windows 10? "


5
Sono d'accordo con la funzione getOSName, sulla base di OAOO (una volta e una sola volta); tuttavia, la memorizzazione nella cache è totalmente ridondante, data la velocità delle ricerche hash.
Chris Jester-Young,

6
Totalmente ridondante potrebbe essere un po 'duro, le ricerche di hash sono più costose dell'accesso a un riferimento. Tutto dipende dal contesto.
Craig Day,

2
Aspetti positivi ... Sentiti libero di votare in basso se pensi che sia una cattiva pratica;)
VonC

5
Rileggo questa risposta Se avete intenzione di cache, cache i valori di isWindows, isUnixecc In questo modo si risparmia sui momento di confronto di stringa anche.
Chris Jester-Young,

2
@Brian True. Ho modificato di conseguenza questa risposta molto vecchia, per fare riferimento a quella più recente.
VonC,

44

alcuni dei collegamenti nelle risposte sopra sembrano essere interrotti. Ho aggiunto i puntatori al codice sorgente corrente nel codice seguente e offro un approccio per gestire il controllo con un enum come risposta in modo che sia possibile utilizzare un'istruzione switch durante la valutazione del risultato:

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

La classe di supporto è:

/**
 * 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) non può mai essere vero perché viene dopo (OS.indexOf ("win")> = 0)
William

14
Il codice sopra riportato potrebbe avere problemi di localizzazione, poiché utilizza toLowerCase (), che è sensibile alla locale. Ciò che importa è in particolare quando converto i in lettere minuscole / maiuscole, poiché in Turchia, divento maiuscolo i non notato i (ı) e divento i maiuscolo punteggiato i (©). Quindi "WINDOWS" .toLowerCase (). IndexOf ("win") restituirà -1 in Turchia. Passare sempre una locale quando si fa una minuscola di una lingua particolare, ad esempio "WINDOWS" .toLowerCase (Locale.ENGLISH) .indexOf ("win") funzionerà in Turchia.
James Roper,

@JamesRoper - grazie risolto questo.
Wolfgang Fahl,

7
OS.contains (...)
Grigory Kislin

42

Le seguenti classi JavaFX hanno metodi statici per determinare il sistema operativo corrente (isWindows (), isLinux () ...):

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

Esempio:

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

questo dovrebbe essere più alto
habitat

3
Si noti che l'accesso a "com / sun / javafx / *" è sconsigliato ora (verificato con JDK 1.8.0_121).
Michael Marton,

1
@MichaelMarton Hai un riferimento per la tua affermazione?
Hummeling Engineering BV,

@HummelingEngineeringBV: immagino sia stato un errore dalla mia parte. Sto lavorando con eclipse Neon 4.6.3 e "Java Build Path" mostra diversi avvisi "Scoraggiato: com / sun / javafx / **". Tuttavia, come ho scoperto, sembra che si tratti di un bug e / o funzionalità di eclissi (vedi link ).
Michael Marton,

2
Devo correggermi ancora una volta. A partire da Java 9 / 10+, stanno per essere rimossi diversi pacchetti / API "com.sun. *". Dai un'occhiata a questo link per maggiori informazioni. In realtà mi sono imbattuto in questo perché usiamo alcuni di questi pacchetti. Migrando a eclipse 4.8 / JDK 10, ora dobbiamo correggere questi e molti altri errori del compilatore a causa di riferimenti mancanti.
Michael Marton,

16

TL; DR

Per accedere l'uso del sistema operativo: System.getProperty("os.name").


Ma perché non creare una classe di utilità, renderla riutilizzabile! E probabilmente molto più veloce su più chiamate. Pulito, chiaro, più veloce!

Creare una classe Util per tali funzioni di utilità. Quindi creare enumerazioni pubbliche per ciascun tipo di sistema operativo.

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

Ora, puoi facilmente invocare la classe da qualsiasi classe come segue (PS Poiché abbiamo dichiarato la variabile os come statica, consumerà tempo solo una volta per identificare il tipo di sistema, quindi può essere utilizzata fino a quando l'applicazione non si arresta.)

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

e questo è tutto!


2
Voglio usare questo pezzo di codice in un progetto open source ( github.com/openhab/openhab-addons ), va bene per te?
Consti P

Sì, sentiti libero di usarlo.
Memin

13

Un piccolo esempio di ciò che stai cercando di ottenere sarebbe probabilmente classsimile a quello che c'è sotto:

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

Questa particolare implementazione è abbastanza affidabile e dovrebbe essere universalmente applicabile. Copialo e incollalo nella tua classscelta.


10

Se sei interessato a come un progetto open source fa cose del genere, puoi dare un'occhiata alla classe Terracotta (Os.java) che gestisce questa spazzatura qui:

E puoi vedere una classe simile per gestire le versioni JVM (Vm.java e VmVersion.java) qui:


2
Quella lezione di terracotta è piuttosto completa!
Stewart,

3
attenzione alla licenza !!
harschware,

soffre anche dello stesso problema identificato da James Roper nella risposta di Wolfgang Fahl - uso di toLowerCasesenza specificare un locale
kbolino

9

Prova questo, semplice e facile

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

9

Tratto da questo progetto 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

Il codice seguente mostra i valori che puoi ottenere dall'API di sistema, tutte queste cose che puoi ottenere attraverso questa 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"));
    }
}

Risposte: -

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

Trovo che il SO Utils di Swingx faccia il suo lavoro.


2
Il link sopra sembra essere rotto, probabilmente a causa dell'introduzione di branch da parte di SwingX; la versione 1.6 è qui: swingx.dev.java.net/source/browse/swingx/tags/SwingX-1-6/src/…
David Moles

1
@ David Moles, grazie. il link era ok quando ho risposto, ora l'ho aggiornato con il tuo.
Richard Harrison,



5
String osName = System.getProperty("os.name");
System.out.println("Operating system " + osName);

4

Puoi semplicemente usare il metodo sun.awt.OSInfo # getOSType ()


Questa dovrebbe essere la risposta migliore! Stavo solo controllando se qualcuno lo ha già menzionato qui.
Martin Krajčírovič,

Qualche soluzione alternativa per questa "API limitata"? Mi piacerebbe provare a usarlo ma mi dà quell'avvertimento in Eclipse. Posso usare un jre più vecchio (ad es. Jre1.8.0_171), ma gli ultimi 1.8 jre lo hanno contrassegnato come limitato.
Brian_Entei

4

Se lavori in un ambiente sensibile alla sicurezza, ti preghiamo di leggere questo.

Si prega di astenersi dal fidarsi mai di una proprietà ottenuta tramite la System#getProperty(String)subroutine! In realtà, quasi tutte le proprietà os.arch, tra cui os.name, eos.version non sono di sola lettura come ci si aspetterebbe - invece, sono in realtà esattamente il contrario.

Prima di tutto, qualsiasi codice con l'autorizzazione sufficiente per invocare la System#setProperty(String, String)subroutine può modificare il valore letterale restituito a piacimento. Tuttavia, questo non è necessariamente il problema principale qui, in quanto può essere risolto mediante l'uso di un cosiddetto SecurityManager, come descritto in maggior dettaglio qui .

Il vero problema è che qualsiasi utente è in grado di modificare queste proprietà durante l'esecuzione della JARdomanda in questione. Ciò significa che non c'è modo di determinare se queste proprietà sono effettivamente accurate. Per questo motivo, ecco alcuni controlli aggiuntivi per cercare di evitare manomissioni:

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

Un'altra buona idea è quella di verificare la presenza di directory specifiche del sistema operativo. Qualunque sia l'approccio che potresti adottare, ricorda che il linguaggio Java è rientrato come multipiattaforma. Quindi, perché non provi a fare lo stesso?


3

Mi è piaciuta la risposta di Wolfgang, solo perché credo che cose del genere dovrebbero essere dei contro ...

quindi l'ho riformulato un po 'per me stesso e ho pensato di condividerlo :)

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

Sembra che "darwin" non possa mai essere abbinato perché il controllo di "win" provocherebbe già la restituzione di Windows.
tvkanters

vedi correzione nella mia risposta originale
Wolfgang Fahl

3
Congratulazioni, hai reimplementato sun.awt.OSInfo # getOSType :)
Kirill Gamazkov il

HHHHH ... buono ... @Kirill Gamazkov non l'ho trovato allora .. grazie per averlo sottolineato
TacB0sS

2

Questo codice per visualizzare tutte le informazioni sul tipo di sistema operativo, il nome, le informazioni Java e così via.

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

Nella classe com.sun.jna.Platform puoi trovare utili metodi statici come

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

e altro ancora.

Se usi Maven aggiungi semplicemente dipendenza

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

Altrimenti basta trovare il file jar della libreria jna (es. Jna-5.2.0.jar) e aggiungerlo al percorso di classe.


1

Basta usare com.sun.javafx.util.Utilscome di seguito.

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

O USARE

boolean isWindows = OSInfo.getOSType().equals(OSInfo.OSType.WINDOWS);
       if (isWindows){
         // YOUR LOGIC HERE
       }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.