Bagaimana cara saya menentukan secara sistematis sistem operasi di Jawa?

526

Saya ingin menentukan sistem operasi host yang dijalankan oleh program Java saya (misalnya: Saya ingin dapat memuat properti yang berbeda berdasarkan apakah saya menggunakan platform Windows atau Unix). Apa cara teraman untuk melakukan ini dengan keandalan 100%?

karlgrz
sumber

Jawaban:

617

Kamu bisa menggunakan:

System.getProperty("os.name")

PS Anda mungkin menemukan kode ini berguna:

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

Yang dilakukannya hanyalah mencetak semua properti yang disediakan oleh implementasi Java Anda. Ini akan memberi Anda gambaran tentang apa yang dapat Anda ketahui tentang lingkungan Java Anda melalui properti. :-)

Chris Jester-Young
sumber
6
Saya menggunakan Windows 10namun os.namememberi saya Windows 8.1. Mengapa demikian? Dari mana datangnya ini?
Brian
152

Seperti yang ditunjukkan dalam jawaban lain, System.getProperty menyediakan data mentah. Namun, komponen Apache Commons Lang menyediakan pembungkus untuk java.lang.System dengan sifat-sifat praktis seperti SystemUtils.IS_OS_WINDOWS, sangat mirip dengan utilitas Swingx OS yang disebutkan di atas.

Leif Carlsen
sumber
2
Itu sangat berguna. Anda menemukan fitur-fitur baru di Apache Lang3 setiap hari!
Robin Jonsson
82

Oktober 2008:

Saya akan merekomendasikan untuk menyimpannya dalam variabel statis:

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
}

Dengan begitu, setiap kali Anda meminta Os, Anda tidak mengambil properti lebih dari satu kali seumur hidup aplikasi Anda.


Februari 2016: 7+ tahun kemudian:

Ada bug dengan Windows 10 (yang tidak ada pada saat jawaban aslinya).
Lihat " Java" os.name "untuk Windows 10? "

VONC
sumber
5
Saya setuju dengan fungsi getOSName, berdasarkan OAOO (sekali dan hanya sekali); Namun, caching benar-benar berlebihan mengingat kecepatan pencarian hash.
Chris Jester-Young
6
Benar-benar berlebihan mungkin agak keras, pencarian hash lebih mahal daripada mengakses referensi. Itu semua tergantung konteksnya.
Craig Day
2
Poin yang bagus ... Jangan ragu untuk memilih jika Anda menganggapnya sebagai praktik yang buruk;)
VonC
5
Saya membaca kembali jawaban ini. Jika Anda akan ke cache, cache nilai-nilai isWindows, isUnixcara, dll Itu Anda menyimpan pada waktu perbandingan string juga.
Chris Jester-Young
2
@Brian Benar. Saya telah mengedit jawaban yang sangat lama ini, untuk merujuk ke yang lebih baru.
VonC
44

beberapa tautan dalam jawaban di atas tampaknya rusak. Saya telah menambahkan pointer ke kode sumber saat ini dalam kode di bawah ini dan menawarkan pendekatan untuk menangani cek dengan enum sebagai jawaban sehingga pernyataan switch dapat digunakan saat mengevaluasi hasilnya:

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

Kelas pembantu adalah:

/**
 * 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
sumber
3
(OS.indexOf ("darwin")> = 0) tidak akan pernah benar karena ia datang setelah (OS.indexOf ("win")> = 0)
William
14
Kode di atas mungkin memiliki masalah lokal, karena menggunakan toLowerCase (), yang sensitif terhadap lokal. Di mana hal ini penting terutama ketika mengubah i menjadi huruf kecil / huruf besar, karena di Turki, saya menjadi huruf kecil undotted i (ı), dan saya menjadi huruf besar titik i (İ). Jadi "WINDOWS" .toLowerCase (). IndexOf ("win") akan mengembalikan -1 di Turki. Selalu berikan lokal ketika melakukan huruf kecil dari bahasa tertentu, yaitu "WINDOWS" .toLowerCase (Locale.ENGLISH) .indexOf ("win") akan berfungsi di Turki.
James Roper
@ JamesRoper - thanx memperbaiki ini.
Wolfgang Fahl
7
OS.contains (...)
Grigory Kislin
42

Kelas JavaFX berikut memiliki metode statis untuk menentukan OS saat ini (isWindows (), isLinux () ...):

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

Contoh:

if (PlatformUtil.isWindows()){
           ...
}
Igor Rybak
sumber
ini harus lebih tinggi
habitat
3
Harap perhatikan bahwa akses ke "com / sun / javafx / *" tidak disarankan sekarang (periksa dengan JDK 1.8.0_121).
Michael Marton
1
@MichaelMarton Punya referensi untuk pernyataan Anda?
Hummeling Engineering BV
@HummelingEngineeringBV: Saya kira itu adalah kesalahan dari pihak saya. Saya bekerja dengan gerhana Neon 4.6.3 dan "Java Build Path" menunjukkan beberapa peringatan "Berkecil hati: com / sun / javafx / **". Namun, seperti yang saya ketahui, ini terjadi pada bug-gerhana dan / atau-fitur (lihat tautan ).
Michael Marton
2
Saya harus memperbaiki diri saya sekali lagi. Dimulai dengan Java 9/10 +, beberapa paket / API "com.sun. *" Akan segera dihapus. Lihat tautan ini untuk info lebih lanjut. Saya benar-benar tersandung ini karena kami menggunakan beberapa paket ini. Bermigrasi ke eclipse 4.8 / JDK 10, kami sekarang harus memperbaiki ini dan beberapa kesalahan kompiler lainnya karena referensi yang hilang.
Michael Marton
16

TL; DR

Untuk mengakses OS penggunaan: System.getProperty("os.name").


Tapi mengapa tidak membuat kelas utilitas, buat itu bisa digunakan kembali! Dan mungkin jauh lebih cepat pada beberapa panggilan. Bersih, jernih, lebih cepat!

Buat kelas Util untuk fungsi utilitas tersebut. Kemudian buat enum publik untuk setiap jenis sistem operasi.

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

Sekarang, Anda dapat dengan mudah memanggil kelas dari kelas mana saja sebagai berikut, (PS Karena kami menyatakan variabel os sebagai statis, itu akan memakan waktu hanya sekali untuk mengidentifikasi jenis sistem, maka itu dapat digunakan sampai aplikasi Anda berhenti.)

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

dan itu dia!

Memin
sumber
2
Saya ingin menggunakan kode ini dalam proyek open-source ( github.com/openhab/openhab-addons ), apakah ini boleh untuk Anda?
Consti P
Ya, silakan menggunakannya.
Memin
13

Contoh kecil dari apa yang ingin Anda capai mungkin classmirip dengan apa yang ada di bawahnya:

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

Implementasi khusus ini cukup dapat diandalkan dan harus dapat diterapkan secara universal. Cukup salin dan tempel ke classpilihan Anda.

Nikesh Jauhari
sumber
10

Jika Anda tertarik pada bagaimana proyek open source melakukan hal-hal seperti ini, Anda dapat melihat kelas Terracotta (Os.java) yang menangani sampah ini di sini:

Dan Anda dapat melihat kelas serupa untuk menangani versi JVM (Vm.java dan VmVersion.java) di sini:

Alex Miller
sumber
2
Kelas Terracotta itu cukup komprehensif!
Stewart
3
Waspadalah terhadap lisensi !!
harschware
juga menderita masalah yang sama yang diidentifikasi oleh James Roper dalam jawaban Wolfgang Fahl - penggunaan toLowerCasetanpa menentukan lokal
kbolino
9

Coba ini, sederhana dan mudah

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

Diambil dari proyek ini 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
sumber
8

Kode di bawah ini menunjukkan nilai-nilai yang bisa Anda dapatkan dari API Sistem, ini semua hal yang bisa Anda dapatkan melalui API ini.

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

Jawaban: -

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

Saya menemukan bahwa Utils OS dari Swingx melakukan pekerjaan.

Richard Harrison
sumber
2
Tautan di atas tampaknya rusak, mungkin karena SwingX memperkenalkan cabang; rilis 1.6 ada di sini: swingx.dev.java.net/source/browse/swingx/tags/SwingX-1-6/src/…
David Moles
1
@ David Moles, terima kasih. tautannya ok ketika saya menjawab - Saya sekarang telah memperbaruinya dengan tautan Anda.
Richard Harrison
2
Versi terbaru ada di sini: 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
sumber
4

Anda cukup menggunakan metode sun.awt.OSInfo # getOSType ()

Kirill Gamazkov
sumber
Ini harus menjadi jawaban terbaik! Saya hanya memeriksa apakah seseorang telah menyebutkan ini di sini.
Martin Krajčírovič
Adakah solusi untuk hal ini menjadi 'API terbatas'? Saya ingin mencoba menggunakan ini tetapi memberi saya peringatan itu di Eclipse. Saya dapat menggunakan jre yang lebih lama (misalnya jre1.8.0_171), tetapi 1,8 jre terbaru ditandai sebagai terbatas.
Brian_Entei
4

Jika Anda bekerja di lingkungan yang peka terhadap keamanan, silakan baca ini.

Harap jangan pernah mempercayai properti yang diperoleh melalui System#getProperty(String)subrutin! Sebenarnya, hampir setiap properti termasuk os.arch,, os.namedan os.versiontidak dibaca hanya seperti yang Anda harapkan - sebagai gantinya, mereka sebenarnya sangat berlawanan.

Pertama-tama, kode apa pun dengan izin yang memadai untuk menjalankan System#setProperty(String, String)subrutin dapat mengubah literal yang dikembalikan sesuka hati. Namun, itu belum tentu masalah utama di sini, karena dapat diselesaikan melalui penggunaan yang disebut SecurityManager, seperti yang dijelaskan secara lebih rinci di sini .

Masalah sebenarnya adalah bahwa setiap pengguna dapat mengedit properti ini ketika menjalankan JARpertanyaan tersebut. Ini berarti bahwa tidak ada cara untuk menentukan apakah properti ini memang benar-benar akurat. Karena itu, berikut adalah beberapa pemeriksaan tambahan untuk mencoba dan menghindari gangguan:

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

Ide bagus lainnya adalah memeriksa keberadaan direktori khusus sistem operasi. Apa pun pendekatan yang Anda ambil, ingatlah bahwa bahasa Jawa diindentasikan sebagai platform silang. Jadi, mengapa Anda tidak mencoba melakukan hal yang sama?

Niklas Simandi
sumber
3

Saya menyukai jawaban Wolfgang, hanya karena saya percaya hal-hal seperti itu harus menjadi konstanta ...

jadi saya ulangi sedikit untuk saya sendiri, dan berpikir untuk membagikannya :)

/**
 * 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
sumber
Sepertinya "darwin" tidak pernah dapat ditandingi karena memeriksa "menang" sudah akan menyebabkan Windows dikembalikan.
tvkanters
lihat memperbaiki dalam jawaban asli saya
Wolfgang Fahl
3
Selamat, Anda telah menerapkan ulang sun.awt.OSInfo # getOSType :)
Kirill Gamazkov
HHHHH ... bagus ... @ Kirill Gamazkov Saya tidak menemukannya saat itu .. terima kasih telah menunjukkannya
TacB0sS
2

Kode ini untuk menampilkan semua informasi tentang jenis sistem os, nama, informasi java dan sebagainya.

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

Di kelas com.sun.jna.Platform Anda dapat menemukan metode statis yang berguna seperti

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

dan banyak lagi.

Jika Anda menggunakan Maven, tambahkan saja ketergantungan

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

Jika tidak, cari saja file jar perpustakaan jna (mis. Jna-5.2.0.jar) dan tambahkan ke classpath.

Vladimir Vaschenko
sumber
1

Gunakan saja com.sun.javafx.util.Utilsseperti di bawah ini.

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

ATAU GUNAKAN

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