¿Cómo determino programáticamente el sistema operativo en Java?

526

Me gustaría determinar el sistema operativo del host que mi programa Java está ejecutando mediante programación (por ejemplo: me gustaría poder cargar diferentes propiedades en función de si estoy en una plataforma Windows o Unix). ¿Cuál es la forma más segura de hacer esto con 100% de confiabilidad?

karlgrz
fuente

Respuestas:

617

Puedes usar:

System.getProperty("os.name")

PD: Puede encontrar útil este código:

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

Todo lo que hace es imprimir todas las propiedades proporcionadas por sus implementaciones de Java. Le dará una idea de lo que puede averiguar sobre su entorno Java a través de propiedades. :-)

Chris Jester-Young
fuente
66
Estoy usando Windows 10y aún os.nameme da Windows 8.1. ¿Porqué es eso? ¿De dónde viene esto?
Brian
82

Octubre de 2008:

Recomendaría almacenarlo en caché en una variable estática:

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 esa manera, cada vez que solicita el sistema operativo, no obtiene la propiedad más de una vez durante la vida útil de su aplicación.


Febrero de 2016: más de 7 años después:

Hay un error con Windows 10 (que no existía en el momento de la respuesta original).
Consulte " Java" os.name "para Windows 10? "

VonC
fuente
55
Estoy de acuerdo con la función getOSName, sobre la base de OAOO (una vez y solo una vez); sin embargo, el almacenamiento en caché es totalmente redundante dada la velocidad de las búsquedas hash.
Chris Jester-Young
66
Totalmente redundante puede ser un poco duro, las búsquedas hash son más caras que acceder a una referencia. Todo depende del contexto.
Craig Day
2
Buenos puntos ... No dude en votar si cree que es una mala práctica;)
VonC
55
Releí esta respuesta. Si usted va a la caché, caché de los valores de isWindows, isUnix, etc. De esa manera ahorrar en el tiempo de comparación de cadenas también.
Chris Jester-Young
2
@Brian True. He editado esta respuesta muy antigua en consecuencia, para referirme a la más reciente.
VonC
44

Algunos de los enlaces en las respuestas anteriores parecen estar rotos. He agregado punteros al código fuente actual en el código a continuación y ofrezco un enfoque para manejar la verificación con una enumeración como respuesta para que se pueda usar una declaración de cambio al evaluar el resultado:

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

La clase auxiliar es:

/**
 * 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
fuente
3
(OS.indexOf ("darwin")> = 0) nunca puede ser cierto porque viene después de (OS.indexOf ("win")> = 0)
William
14
El código anterior puede tener problemas de configuración regional, ya que utiliza toLowerCase (), que es sensible a la configuración regional. Donde esto importa es particularmente cuando se convierten las i en minúsculas / mayúsculas, ya que en Turquía, me convierto en minúsculas i (ı), y me convierto en mayúsculas i (İ). Entonces "WINDOWS" .toLowerCase (). IndexOf ("win") devolverá -1 en Turquía. Siempre pase una configuración regional al hacer minúsculas de un idioma en particular, es decir, "WINDOWS" .toLowerCase (Locale.ENGLISH) .indexOf ("win") funcionará en Turquía.
James Roper
@JamesRoper - thanx arregló esto.
Wolfgang Fahl el
77
OS.contains (...)
Grigory Kislin
42

Las siguientes clases JavaFX tienen métodos estáticos para determinar el sistema operativo actual (isWindows (), isLinux () ...):

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

Ejemplo:

if (PlatformUtil.isWindows()){
           ...
}
Igor Rybak
fuente
esto debería ser más alto
hábitats
3
Tenga en cuenta que el acceso a "com / sun / javafx / *" no se recomienda ahora (verifíquelo con JDK 1.8.0_121).
Michael Marton
1
@MichaelMarton ¿Tiene una referencia para su declaración?
Hummeling Engineering BV
@HummelingEngineeringBV: Supongo que fue un error de mi parte. Estoy trabajando con eclipse Neon 4.6.3 y el "Java Build Path" muestra varias advertencias "Desalentado: com / sun / javafx / **". Sin embargo, como descubrí, se trata de un eclipse-bug y / o -feature (ver enlace ).
Michael Marton
2
Tengo que corregirme una vez más. A partir de Java 9/10 +, varios paquetes / API "com.sun. *" Están a punto de eliminarse. Mira este enlace para más información. En realidad me topé con esto porque usamos algunos de estos paquetes. Al migrar a eclipse 4.8 / JDK 10, ahora tenemos que corregir estos y otros errores del compilador debido a la falta de referencias.
Michael Marton
16

TL; DR

Para acceder a su uso OS: System.getProperty("os.name").


Pero, ¿por qué no crear una clase de utilidad, hacerla reutilizable! Y probablemente mucho más rápido en múltiples llamadas. ¡Limpio, claro, más rápido!

Cree una clase Util para tales funciones de utilidad. Luego, cree enumeraciones públicas para cada tipo de 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;
    }
}

Ahora, puede invocar fácilmente la clase desde cualquier clase de la siguiente manera, (PD: ya que declaramos la variable os como estática, consumirá tiempo solo una vez para identificar el tipo de sistema, luego se puede usar hasta que su aplicación se detenga).

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

¡y eso es todo!

Memin
fuente
2
Quiero usar este fragmento de código en un proyecto de código abierto ( github.com/openhab/openhab-addons ), ¿te parece bien?
Consti P
Sí, no dudes en usarlo.
Memin
13

Un pequeño ejemplo de lo que está tratando de lograr probablemente sería classsimilar a lo que hay debajo:

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

Esta implementación particular es bastante confiable y debería ser universalmente aplicable. Simplemente cópielo y péguelo en su classelección.

Nikesh Jauhari
fuente
10

Si está interesado en cómo un proyecto de código abierto hace cosas como esta, puede consultar la clase de terracota (Os.java) que maneja esta basura aquí:

Y puede ver una clase similar para manejar versiones JVM (Vm.java y VmVersion.java) aquí:

Alex Miller
fuente
2
¡Esa clase de terracota es bastante completa!
Stewart
3
cuidado con la licencia !!
harschware
también sufre el mismo problema identificado por James Roper en la respuesta de Wolfgang Fahl - uso de toLowerCasesin especificar una ubicación
kbolino
9

Prueba esto, simple y fácil

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

Tomado de este proyecto 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
fuente
8

El siguiente código muestra los valores que puede obtener de la API del sistema, todo lo que puede obtener a través de esta 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"));
    }
}

Respuestas: -

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
fuente
7

Encuentro que las utilidades del sistema operativo de Swingx hacen el trabajo.

Richard Harrison
fuente
2
El enlace anterior parece estar roto, probablemente debido a la introducción de ramas de SwingX; la versión 1.6 está aquí: swingx.dev.java.net/source/browse/swingx/tags/SwingX-1-6/src/…
David Moles
1
@ David Moles, gracias. el enlace estaba bien cuando respondí, ahora lo actualicé con el tuyo.
Richard Harrison
2
La última versión está aquí: 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
fuente
4

Puede usar el método sun.awt.OSInfo # getOSType ()

Kirill Gamazkov
fuente
¡Esta debería ser la mejor respuesta! Solo estaba comprobando si alguien ya ha mencionado esto aquí.
Martin Krajčírovič
¿Alguna solución para esto es 'API restringida'? Me gustaría intentar usar esto, pero me da esa advertencia en Eclipse. Puedo usar un jre anterior (por ejemplo, jre1.8.0_171), pero los últimos 1.8 jres lo tienen marcado como restringido.
Brian_Entei
4

Si está trabajando en un entorno sensible a la seguridad, lea esto detenidamente.

¡Abstenerse de confiar en una propiedad obtenida a través de la System#getProperty(String)subrutina! En realidad, casi todas las propiedades os.arch, incluidos os.name, yos.version no son de solo lectura como cabría esperar; en cambio, en realidad son todo lo contrario.

En primer lugar, cualquier código con permiso suficiente para invocar la System#setProperty(String, String)subrutina puede modificar el literal devuelto a voluntad. Sin embargo, ese no es necesariamente el problema principal aquí, ya que se puede resolver mediante el uso de un llamado SecurityManager, como se describe en mayor detalle aquí .

El problema real es que cualquier usuario puede editar estas propiedades cuando ejecuta el JARen cuestión. Esto significa que no hay forma de determinar si estas propiedades son realmente precisas. Debido a esto, aquí hay algunas comprobaciones adicionales para tratar de evitar la manipulación:

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

Otra buena idea es verificar la presencia de directorios específicos del sistema operativo. Cualquiera que sea el enfoque que tome, recuerde que el lenguaje Java está diseñado para ser la plataforma cruzada. Entonces, ¿por qué no intentas hacer lo mismo?

Niklas Simandi
fuente
3

Me gustó la respuesta de Wolfgang, solo porque creo que cosas así deberían ser const ...

así que lo reformulé un poco para mí y pensé en compartirlo :)

/**
 * 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
fuente
Parece que "darwin" nunca puede ser igualado porque al marcar "win" ya se devolvería Windows.
tvkanters
ver arreglo en mi respuesta original
Wolfgang Fahl
3
Felicitaciones, ha reimplementado sun.awt.OSInfo # getOSType :)
Kirill Gamazkov
HHHHH ... bueno ... @Kirill Gamazkov No lo encontré en ese entonces ... gracias por señalarlo
TacB0sS
2

Este código para mostrar toda la información sobre el tipo de sistema operativo, nombre, información de 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
fuente
1

En la clase com.sun.jna.Platform puedes encontrar métodos estáticos útiles como

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

y mucho más.

Si usa Maven simplemente agregue dependencia

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

De lo contrario, solo busque el archivo jar de la biblioteca jna (por ejemplo, jna-5.2.0.jar) y agréguelo a classpath.

Vladimir Vaschenko
fuente
1

Solo use com.sun.javafx.util.Utilscomo a continuación.

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

O USAR

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