Como determino programaticamente o sistema operacional em Java?

526

Gostaria de determinar o sistema operacional do host que meu programa Java está executando programaticamente (por exemplo: gostaria de poder carregar propriedades diferentes, dependendo de eu estar em uma plataforma Windows ou Unix). Qual é a maneira mais segura de fazer isso com 100% de confiabilidade?

karlgrz
fonte

Respostas:

617

Você pode usar:

System.getProperty("os.name")

PS Você pode achar este código útil:

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

Tudo o que faz é imprimir todas as propriedades fornecidas por suas implementações Java. Isso lhe dará uma idéia do que você pode descobrir sobre seu ambiente Java por meio de propriedades. :-)

Chris Jester-Young
fonte
6
Estou usando Windows 10e ainda os.nameme dá Windows 8.1. Por que é que? De onde isso vem?
7777 Brian
82

Outubro de 2008:

Eu recomendaria armazená-lo em cache em uma variável 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
}

Dessa forma, toda vez que você solicitar o sistema operacional, você não buscará a propriedade mais de uma vez durante a vida útil do seu aplicativo.


Fevereiro de 2016: mais de 7 anos depois:

Há um erro no Windows 10 (que não existia no momento da resposta original).
Consulte " os.name de Java‘’para Windows 10? "

VonC
fonte
5
Eu concordo com a função getOSName, com base no OAOO (uma vez e apenas uma vez); no entanto, o cache é totalmente redundante, dada a velocidade das pesquisas de hash.
Chris Jester-Young
6
Totalmente redundante pode ser um pouco duro, as pesquisas de hash são mais caras do que acessar uma referência. Tudo depende do contexto.
Craig Day
2
Bons pontos ... Sinta-se livre para votar se você acha que é uma prática ruim;)
VonC 23/10/08
5
Reli essa resposta. Se você estiver indo para cache, cache os valores de isWindows, isUnix, etc. Dessa forma você economiza o tempo comparação de string também.
Chris Jester-Young
2
@Brian True. Eu editei esta resposta muito antiga de acordo, para se referir à mais recente.
VonC 7/02/16
44

alguns dos links nas respostas acima parecem estar quebrados. Adicionei ponteiros ao código-fonte atual no código abaixo e ofereço uma abordagem para lidar com a verificação com uma enumeração como resposta, para que uma instrução switch possa ser usada ao avaliar o resultado:

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

A classe auxiliar é:

/**
 * 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
fonte
3
(OS.indexOf ("darwin")> = 0) nunca pode ser verdade porque é posterior a (OS.indexOf ("win")> = 0) #
William William
14
O código acima pode ter problemas de localidade, pois usa toLowerCase (), que é sensível à localidade. Onde isso importa, principalmente, ao converter i para minúscula / maiúscula, uma vez que, na Turquia, minúscula não é tracejada i (ı) e i é maiúscula, pontilhada i (©). Portanto, "WINDOWS" .toLowerCase (). IndexOf ("win") retornará -1 na Turquia. Sempre passe um código de idioma ao usar letras minúsculas em um idioma específico, ou seja, "WINDOWS" .toLowerCase (Locale.ENGLISH) .indexOf ("win") funcionará na Turquia.
22814 James Roper #
@JamesRoper - thanx corrigiu isso.
Wolfgang Fahl
7
(...)
Grigory Kislin /
42

As seguintes classes JavaFX possuem métodos estáticos para determinar o SO atual (isWindows (), isLinux () ...):

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

Exemplo:

if (PlatformUtil.isWindows()){
           ...
}
Igor Rybak
fonte
isso deve ser maior
habitats
3
Observe que o acesso a "com / sun / javafx / *" é desencorajado agora (verifique com o JDK 1.8.0_121).
Michael Marton
1
@MichaelMarton Tem uma referência para a sua declaração?
Hummeling Engineering BV
@HummelingEngineeringBV: Eu acho que foi um erro do meu lado. Estou trabalhando com o eclipse Neon 4.6.3 e o "Java Build Path" mostra vários avisos "Desencorajados: com / sun / javafx / **". No entanto, como descobri, isso é um bug de eclipse e / ou uma característica (consulte o link ).
Michael Marton
2
Eu tenho que me corrigir mais uma vez. A partir do Java 9/10 +, vários pacotes / APIs "com.sun. *" Estão prestes a ser removidos. Confira este link para mais informações. Na verdade, eu tropecei nisso porque usamos alguns desses pacotes. Ao migrar para o eclipse 4.8 / JDK 10, agora precisamos corrigir esses e vários outros erros do compilador devido à falta de referências.
Michael Marton
16

TL; DR

Para acessar o uso OS: System.getProperty("os.name").


Mas por que não criar uma classe de utilidade, torne-a reutilizável! E provavelmente muito mais rápido em várias chamadas. Limpo, claro, mais rápido!

Crie uma classe Util para essas funções utilitárias. Em seguida, crie enumerações públicas para cada tipo de sistema operacional.

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

Agora, você pode invocar facilmente a classe de qualquer classe da seguinte maneira (PS: Como declaramos a variável os como estática, ele consumirá tempo apenas uma vez para identificar o tipo de sistema e poderá ser usado até que o aplicativo pare.)

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

e é isso aí!

Memin
fonte
2
Quero usar esse trecho de código em um projeto de código-fonte aberto ( github.com/openhab/openhab-addons ), está tudo bem com você?
Consti P
Sim, sinta-se à vontade para usá-lo.
Memin 12/01
13

Um pequeno exemplo do que você está tentando alcançar provavelmente seria classsemelhante ao que está abaixo:

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

Essa implementação específica é bastante confiável e deve ser universalmente aplicável. Basta copiar e colar na sua classescolha.

Nikesh Jauhari
fonte
10

Se você estiver interessado em saber como um projeto de código aberto faz coisas como essa, confira a classe Terracotta (Os.java) que lida com esse lixo aqui:

E você pode ver uma classe semelhante para lidar com versões da JVM (Vm.java e VmVersion.java) aqui:

Alex Miller
fonte
2
Essa classe de terracota é bastante abrangente!
Stewart
3
cuidado com a licença !!
harschware
também sofre com o mesmo problema identificado por James Roper na resposta de Wolfgang Fahl - uso de toLowerCasesem especificar uma localidade
kbolino
9

Experimente isso, simples e fácil

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

Retirado deste projeto 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
fonte
8

O código abaixo mostra os valores que você pode obter da API do sistema, tudo o que você pode obter com essa 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"));
    }
}

Respostas: -

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

Acho que o OS Utils da Swingx faz o trabalho.

Richard Harrison
fonte
2
O link acima parece estar quebrado, provavelmente devido à introdução de ramificações do SwingX; o lançamento da versão 1.6 está aqui: swingx.dev.java.net/source/browse/swingx/tags/SwingX-1-6/src/…
David Moles
1
@ David Moles, obrigado. o link estava ok quando eu respondi - agora o atualizei com o seu.
Richard Harrison
2
Versão mais recente está aqui: 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
fonte
4

Você pode apenas usar o método sun.awt.OSInfo # getOSType ()

Kirill Gamazkov
fonte
Essa deve ser a melhor resposta! Eu estava apenas checando se alguém já mencionou isso aqui.
Martin Krajčírovič 23/08
Alguma solução alternativa para isso ser 'API restrita'? Eu gostaria de tentar usar isso, mas isso me dá esse aviso no Eclipse. Eu posso usar um jre mais antigo (por exemplo, jre1.8.0_171), mas os últimos 1.8 jres o marcam como restrito.
Brian_Entei
4

Se você estiver trabalhando em um ambiente sensível à segurança, leia isso.

Evite sempre confiar em um imóvel obtido através da System#getProperty(String)sub - rotina! Na verdade, quase todas as propriedades os.arch, incluindo ,, os.namee os.versionnão são apenas de leitura, como seria de esperar - em vez disso, elas são exatamente o oposto.

Antes de tudo, qualquer código com permissão suficiente para chamar a System#setProperty(String, String)sub - rotina pode modificar o literal retornado à vontade. No entanto, essa não é necessariamente a questão principal aqui, pois ela pode ser resolvida com o uso de uma chamada SecurityManager, conforme descrito em maiores detalhes aqui .

O problema real é que qualquer usuário pode editar essas propriedades ao executar o JARem questão. Isso significa que não há como determinar se essas propriedades são realmente precisas. Por esse motivo, seguem algumas verificações adicionais para tentar evitar a violação:

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

Outra boa idéia é verificar a presença de diretórios específicos do sistema operacional. Qualquer que seja a abordagem que você adote, lembre-se de que a linguagem Java é recuada para ser a plataforma cruzada. Então, por que você não tenta fazer o mesmo?

Niklas Simandi
fonte
3

Gostei da resposta de Wolfgang, só porque acredito que coisas assim devem ser consasadas ...

então reformulei um pouco para mim e pensei em compartilhá-lo :)

/**
 * 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
fonte
Parece que "darwin" nunca pode ser correspondido porque marcar "win" já faria com que o Windows fosse retornado.
Tvkanters 29/03
veja correção na minha resposta inicial
Wolfgang Fahl
3
Parabéns, você reimplemented sun.awt.OSInfo # getOSType :)
Kirill Gamazkov
HHHHH ... bom ... @Kirill Gamazkov eu não encontrá-lo naquela época .. obrigado por apontar isso
TacB0sS
2

Este código para exibir todas as informações sobre o sistema, tipo, nome, informações sobre java e assim por diante.

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

Na classe com.sun.jna.Platform, você pode encontrar métodos estáticos úteis, como

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

e muito mais.

Se você usa o Maven, basta adicionar dependência

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

Caso contrário, basta encontrar o arquivo jar da biblioteca jna (por exemplo, jna-5.2.0.jar) e adicioná-lo ao classpath.

Vladimir Vaschenko
fonte
1

Basta usar com.sun.javafx.util.Utilscomo abaixo.

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

OU UTILIZAÇÃO

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