Comment déterminer par programme le système d'exploitation en Java?

526

Je voudrais déterminer le système d'exploitation de l'hôte que mon programme Java exécute par programme (par exemple: je voudrais pouvoir charger différentes propriétés selon que je suis sur une plate-forme Windows ou Unix). Quelle est la façon la plus sûre de le faire avec une fiabilité à 100%?

karlgrz
la source

Réponses:

617

Vous pouvez utiliser:

System.getProperty("os.name")

PS Vous pouvez trouver ce code utile:

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

Il ne fait qu'imprimer toutes les propriétés fournies par vos implémentations Java. Cela vous donnera une idée de ce que vous pouvez découvrir sur votre environnement Java via les propriétés. :-)

Chris Jester-Young
la source
6
J'utilise Windows 10et pourtant os.nameme donne Windows 8.1. Pourquoi donc? D'où cela vient-il?
Brian
152

Comme indiqué dans d'autres réponses, System.getProperty fournit les données brutes. Cependant, le composant Apache Commons Lang fournit un wrapper pour java.lang.System avec des propriétés pratiques comme SystemUtils.IS_OS_WINDOWS, tout comme l'utilitaire Swingx OS susmentionné.

Leif Carlsen
la source
2
C'est vraiment pratique. Vous découvrez chaque jour de nouvelles fonctionnalités dans Apache Lang3!
Robin Jonsson
82

Octobre 2008:

Je recommanderais de le mettre en cache dans une variable statique:

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
}

De cette façon, chaque fois que vous demandez l'Os, vous ne récupérez pas la propriété plus d'une fois dans la durée de vie de votre application.


Février 2016: 7+ ans plus tard:

Il y a un bug avec Windows 10 (qui n'existait pas au moment de la réponse d'origine).
Voir " Java" os.name "pour Windows 10? "

VonC
la source
5
Je suis d'accord avec la fonction getOSName, sur la base de OAOO (une et une seule fois); cependant, la mise en cache est totalement redondante compte tenu de la vitesse des recherches de hachage.
Chris Jester-Young
6
Totalement redondant peut être un peu dur, les recherches de hachage sont plus chères que l'accès à une référence. Tout dépend du contexte.
Craig Day
2
Bons points ... N'hésitez pas à voter contre si vous pensez que c'est une mauvaise pratique;)
VonC
5
J'ai relu cette réponse. Si vous allez cache, cache les valeurs de isWindows, isUnixetc. De cette façon , vous économisez sur le temps de comparaison de chaînes également.
Chris Jester-Young
2
@Brian True. J'ai modifié cette très ancienne réponse en conséquence, pour me référer à la plus récente.
VonC
44

certains des liens dans les réponses ci-dessus semblent rompus. J'ai ajouté des pointeurs vers le code source actuel dans le code ci-dessous et propose une approche pour gérer la vérification avec une énumération comme réponse afin qu'une instruction switch puisse être utilisée lors de l'évaluation du résultat:

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

La classe d'assistance est:

/**
 * 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
la source
3
(OS.indexOf ("darwin")> = 0) ne peut jamais être vrai car il vient après (OS.indexOf ("win")> = 0)
William
14
Le code ci - dessus peut avoir des problèmes de paramètres régionaux, car il utilise toLowerCase (), qui est sensible aux paramètres régionaux. Lorsque cela est particulièrement important lors de la conversion des i en minuscules / majuscules, car en Turquie, je devient minuscule non pointé i (ı), et i devient majuscule pointé i (İ). Ainsi, "WINDOWS" .toLowerCase (). IndexOf ("win") renverra -1 en Turquie. Toujours passer un paramètre régional lorsque vous réduisez la casse d'une langue particulière, c'est-à-dire "WINDOWS" .toLowerCase (Locale.ENGLISH) .indexOf ("win") fonctionnera en Turquie.
James Roper
@JamesRoper - merci a corrigé cela.
Wolfgang Fahl
7
OS.contient (...)
Grigory Kislin
42

Les classes JavaFX suivantes ont des méthodes statiques pour déterminer le système d'exploitation actuel (isWindows (), isLinux () ...):

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

Exemple:

if (PlatformUtil.isWindows()){
           ...
}
Igor Rybak
la source
cela devrait être plus élevé
habitats
3
Veuillez noter que l'accès à "com / sun / javafx / *" est maintenant déconseillé (vérifié avec JDK 1.8.0_121).
Michael Marton
1
@MichaelMarton Avez-vous une référence pour votre déclaration?
Hummeling Engineering BV
@HummelingEngineeringBV: Je suppose que c'était une erreur de mon côté. Je travaille avec eclipse Neon 4.6.3 et le "Java Build Path" affiche plusieurs avertissements "Discouraged: com / sun / javafx / **". Cependant, comme je l'ai découvert, cela se trouve être un bug et / ou une fonction d'éclipse (voir le lien ).
Michael Marton
2
Je dois me corriger une fois de plus. Depuis Java 9/10 +, plusieurs packages / API "com.sun. *" Sont sur le point d'être supprimés. Consultez ce lien pour plus d'informations. En fait, je suis tombé sur cela parce que nous utilisons certains de ces packages. En migrant vers eclipse 4.8 / JDK 10, nous devons maintenant corriger ces erreurs et plusieurs autres erreurs du compilateur en raison de références manquantes.
Michael Marton
16

TL; DR

Pour accéder à l' utilisation du système d'exploitation: System.getProperty("os.name").


Mais pourquoi ne pas créer une classe utilitaire, la rendre réutilisable! Et probablement beaucoup plus rapide sur plusieurs appels. Propre, clair, plus rapide!

Créez une classe Util pour ces fonctions utilitaires. Créez ensuite des énumérations publiques pour chaque type de système d'exploitation.

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

Maintenant, vous pouvez facilement appeler une classe à partir de n'importe quelle classe comme suit, (PS Puisque nous avons déclaré la variable os comme statique, elle ne prendra du temps qu'une seule fois pour identifier le type de système, puis elle peut être utilisée jusqu'à ce que votre application s'arrête.)

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

et c'est tout!

Memin
la source
2
Je veux utiliser ce morceau de code dans un projet open-source ( github.com/openhab/openhab-addons ), cela vous convient-il?
Consti P
Oui, n'hésitez pas à l'utiliser.
Memin
13

Un petit exemple de ce que vous essayez de réaliser serait probablement classsimilaire à ce qui se trouve en dessous:

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

Cette mise en œuvre particulière est assez fiable et devrait être universellement applicable. Copiez-le et collez-le dans votre classchoix.

Nikesh Jauhari
la source
10

Si vous êtes intéressé par la façon dont un projet open source fait des choses comme ça, vous pouvez consulter la classe Terracotta (Os.java) qui gère ces indésirables ici:

Et vous pouvez voir une classe similaire pour gérer les versions JVM (Vm.java et VmVersion.java) ici:

Alex Miller
la source
2
Ce cours en terre cuite est assez complet!
Stewart
3
méfiez-vous de la licence !!
harschware
souffre également du même problème identifié par James Roper dans la réponse de Wolfgang Fahl - utilisation de toLowerCasesans spécifier de lieu
kbolino
9

Essayez ceci, simple et facile

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

Tiré de ce projet 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
la source
8

Le code ci-dessous montre les valeurs que vous pouvez obtenir de l'API système, toutes ces choses que vous pouvez obtenir via cette 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"));
    }
}

Réponses:-

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
la source
7

Je trouve que l' OS Utils de Swingx fait le travail.

Richard Harrison
la source
2
Le lien ci-dessus semble rompu, probablement en raison de l'introduction de branches par SwingX; la version 1.6 est ici: swingx.dev.java.net/source/browse/swingx/tags/SwingX-1-6/src/…
David Moles
1
@David Moles, merci. le lien était ok quand j'ai répondu - je l'ai maintenant mis à jour avec le vôtre.
Richard Harrison
2
La dernière version est ici: 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
la source
4

Vous pouvez simplement utiliser la méthode sun.awt.OSInfo # getOSType ()

Kirill Gamazkov
la source
Cela devrait être la meilleure réponse! Je vérifiais simplement si quelqu'un l'avait déjà mentionné ici.
Martin Krajčírovič
Une solution de contournement pour cela étant une «API restreinte»? Je voudrais essayer de l'utiliser, mais cela me donne cet avertissement dans Eclipse. Je peux utiliser un jre plus ancien (par exemple jre1.8.0_171), mais les derniers 1.8 jres l'ont marqué comme restreint.
Brian_Entei
4

Si vous travaillez dans un environnement sensible à la sécurité, veuillez le lire attentivement.

Veuillez ne jamais faire confiance à une propriété obtenue via le System#getProperty(String)sous - programme! En fait, presque toutes les propriétés, y compris os.arch, os.nameet os.versionne sont pas en lecture seule comme on pourrait s'y attendre - au lieu de cela, elles sont en fait tout à fait le contraire.

Tout d'abord, tout code disposant d'une autorisation suffisante pour invoquer le System#setProperty(String, String)sous - programme peut modifier le littéral renvoyé à volonté. Cependant, ce n'est pas nécessairement le problème principal ici, car il peut être résolu en utilisant un soi-disant SecurityManager, comme décrit plus en détail ici .

Le problème réel est que tout utilisateur peut modifier ces propriétés lors de l'exécution de la JARquestion. Cela signifie qu'il n'y a aucun moyen de déterminer si ces propriétés sont effectivement exactes. Pour cette raison, voici quelques vérifications supplémentaires pour essayer d'éviter toute falsification:

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

Une autre bonne idée est de vérifier la présence de répertoires spécifiques au système d'exploitation. Quelle que soit l'approche que vous puissiez adopter, n'oubliez pas que le langage Java est en retrait pour être la plateforme multiplateforme. Alors, pourquoi n'essayez-vous pas de faire de même?

Niklas Simandi
la source
3

J'ai aimé la réponse de Wolfgang, juste parce que je crois que des choses comme ça devraient être constantes ...

donc je l'ai reformulé un peu pour moi, et j'ai pensé le partager :)

/**
 * 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
la source
Il semble que "darwin" ne puisse jamais être mis en correspondance car la vérification de "win" entraînerait déjà le retour de Windows.
tvkanters
voir la correction dans ma réponse originale
Wolfgang Fahl
3
Félicitations, vous avez réimplémenté sun.awt.OSInfo # getOSType :)
Kirill Gamazkov
HHHHH ... bon ... @Kirill Gamazkov Je ne l'ai pas trouvé à l'époque .. merci de l'avoir signalé
TacB0sS
2

Ce code pour afficher toutes les informations sur le type de système d'exploitation, le nom, les informations java, etc.

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
la source
1

Dans la classe com.sun.jna.Platform, vous pouvez trouver des méthodes statiques utiles comme

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

et beaucoup plus.

Si vous utilisez Maven, ajoutez simplement la dépendance

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

Sinon, il suffit de trouver le fichier jar de la bibliothèque jna (ex. Jna-5.2.0.jar) et de l'ajouter à classpath.

Vladimir Vaschenko
la source
1

Utilisez simplement com.sun.javafx.util.Utilscomme ci-dessous.

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

OU UTILISER

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