Làm cách nào để tôi xác định lập trình hệ điều hành trong Java?


526

Tôi muốn xác định hệ điều hành của máy chủ lưu trữ rằng chương trình Java của tôi đang chạy theo chương trình (ví dụ: Tôi muốn có thể tải các thuộc tính khác nhau dựa trên việc tôi đang ở trên nền tảng Windows hay Unix). Cách an toàn nhất để làm điều này với độ tin cậy 100% là gì?

Câu trả lời:


617

Bạn có thể dùng:

System.getProperty("os.name")

PS Bạn có thể thấy mã này hữu ích:

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

Tất cả những gì nó làm là in ra tất cả các thuộc tính được cung cấp bởi các triển khai Java của bạn. Nó sẽ cho bạn ý tưởng về những gì bạn có thể tìm hiểu về môi trường Java của mình thông qua các thuộc tính. :-)


6
Tôi đang sử dụng Windows 10os.namecung cấp cho tôi Windows 8.1. Tại sao vậy? Cái này đến từ đâu vậy?
Brian


152

Như đã chỉ ra trong các câu trả lời khác, System.getProperty cung cấp dữ liệu thô. Tuy nhiên, thành phần Apache Commons Lang cung cấp trình bao bọc cho java.lang.System với các thuộc tính tiện dụng như SystemUtils.IS_OS_WINDOWS, giống như sử dụng hệ điều hành Swingx đã nói ở trên.


2
Điều đó thực sự tiện dụng. Bạn khám phá các tính năng mới trong Apache Lang3 mỗi ngày!
Robin Jonsson

82

Tháng 10 năm 2008:

Tôi khuyên bạn nên lưu trữ nó trong một biến tĩnh:

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
}

Bằng cách đó, mỗi khi bạn yêu cầu Os, bạn không tìm nạp tài sản nhiều hơn một lần trong suốt vòng đời của ứng dụng của mình.


Tháng 2 năm 2016: 7+ năm sau:

Có một lỗi với Windows 10 (không tồn tại tại thời điểm trả lời ban đầu).
Xem " Java's os osname name cho Windows 10? "


5
Tôi đồng ý với chức năng getOSName, trên cơ sở OAOO (một lần và chỉ một lần); tuy nhiên, bộ nhớ đệm hoàn toàn dư thừa với tốc độ tra cứu băm.
Chris Jester-Young

6
Hoàn toàn dư thừa có thể là một chút khắc nghiệt, tra cứu băm đắt hơn so với truy cập một tài liệu tham khảo. Tất cả phụ thuộc vào bối cảnh.
Ngày Craig ngày

2
Điểm tốt ... Hãy thoải mái bỏ phiếu nếu bạn cho rằng đó là một thực tiễn tồi;)
VonC

5
Tôi đọc lại câu trả lời này. Nếu bạn đang đi để bộ nhớ cache, bộ nhớ cache các giá trị của isWindows, isUnixcách, vv Đó giúp bạn tiết kiệm trên chuỗi thời gian so sánh cũng có.
Chris Jester-Young

2
@Brian Đúng. Tôi đã chỉnh sửa câu trả lời rất cũ này cho phù hợp, để tham khảo câu trả lời gần đây hơn.
VonC

44

một số liên kết trong các câu trả lời ở trên dường như bị phá vỡ. Tôi đã thêm con trỏ vào mã nguồn hiện tại trong mã bên dưới và đưa ra cách tiếp cận để xử lý kiểm tra với enum như một câu trả lời để có thể sử dụng câu lệnh chuyển đổi khi đánh giá kết quả:

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

Lớp người trợ giúp là:

/**
 * 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) không bao giờ có thể đúng bởi vì nó xuất hiện sau (OS.indexOf ("win")> = 0)
William

14
Mã ở trên có thể có vấn đề về miền địa phương, vì nó sử dụng toLowerCase (), là ngôn ngữ nhạy cảm. Trường hợp vấn đề này đặc biệt khi chuyển đổi i thành chữ thường / chữ thường, vì ở Thổ Nhĩ Kỳ, tôi trở thành chữ thường không bị xóa i (ı) và tôi trở thành chữ hoa viết hoa chữ thường (i). Vì vậy, "WINDOWS" .toLowerCase (). IndexOf ("win") sẽ trả về -1 ở Thổ Nhĩ Kỳ. Luôn luôn vượt qua một ngôn ngữ khi viết chữ thường của một ngôn ngữ cụ thể, tức là "WINDOWS" .toLowerCase (Locale.ENG setup) .indexOf ("win") sẽ hoạt động ở Thổ Nhĩ Kỳ.
James Roper

@JamesRoper - thanx đã sửa lỗi này.
Wolfgang Fahl

7
OS.contains (...)
Grigory Kislin 13/03/2015

42

Các lớp JavaFX sau đây có các phương thức tĩnh để xác định HĐH hiện tại (isWindows (), isLinux () ...):

  • com.sun.javafx.Pl platformUtil
  • com.sun.media.jfxmediaimpl.HostUtils
  • com.sun.javafx.util.Utils

Thí dụ:

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

điều này nên cao hơn
môi trường sống

3
Xin lưu ý rằng quyền truy cập vào "com / sun / javafx / *" hiện không được khuyến khích (đã kiểm tra nó bằng JDK 1.8.0_121).
Michael Marton

1
@MichaelMarton Bạn có tài liệu tham khảo cho tuyên bố của mình không?
Hummeling Engineering BV

@HummelingEngineeringBV: Tôi đoán đó là một sai lầm từ phía tôi. Tôi đang làm việc với nhật thực neon 4.6.3 và "Đường dẫn xây dựng Java" hiển thị một số cảnh báo "Không khuyến khích: com / sun / javafx / **". Tuy nhiên, như tôi đã tìm ra, đây là một lỗi nhật thực và / hoặc -feature (xem liên kết ).
Michael Marton

2
Tôi phải sửa mình thêm một lần nữa. Bắt đầu với Java 9/10 +, một số gói / API "com.sun. *" Sắp bị xóa. Kiểm tra liên kết này để biết thêm. Tôi thực sự vấp phải điều này bởi vì chúng tôi sử dụng một số các gói này. Di chuyển sang nhật thực 4,8 / JDK 10, bây giờ chúng ta phải sửa những lỗi này và một số lỗi trình biên dịch khác do thiếu các tham chiếu.
Michael Marton

16

TL; DR

Để truy cập hệ điều hành, sử dụng : System.getProperty("os.name").


Nhưng tại sao không tạo ra một lớp tiện ích, làm cho nó có thể tái sử dụng! Và có lẽ nhanh hơn nhiều trên nhiều cuộc gọi. Sạch sẽ, rõ ràng, nhanh hơn!

Tạo một lớp Util cho các chức năng tiện ích như vậy. Sau đó tạo enum công khai cho từng loại hệ điều hành.

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

Bây giờ, bạn có thể dễ dàng gọi lớp từ bất kỳ lớp nào như sau, (PS Vì chúng tôi đã khai báo biến os là tĩnh, nên sẽ chỉ mất một lần thời gian để xác định loại hệ thống, sau đó nó có thể được sử dụng cho đến khi ứng dụng của bạn tạm dừng.)

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

Và đó là nó!


2
Tôi muốn sử dụng đoạn mã này trong một dự án nguồn mở ( github.com/openhab/openhab-addons ), điều này có ổn với bạn không?
Consti P

Có, xin vui lòng sử dụng nó.
Memin

13

Một ví dụ nhỏ về những gì bạn đang cố gắng đạt được có thể classtương tự như những gì bên dưới:

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

Việc thực hiện cụ thể này là khá đáng tin cậy và nên được áp dụng phổ biến. Chỉ cần sao chép và dán nó vào classsự lựa chọn của bạn .


10

Nếu bạn quan tâm đến cách một dự án nguồn mở thực hiện những thứ như thế này, bạn có thể xem lớp Terracotta (Os.java) xử lý rác này tại đây:

Và bạn có thể thấy một lớp tương tự để xử lý các phiên bản JVM (Vm.java và VmVersion.java) tại đây:


2
Lớp đất nung đó khá toàn diện!
Stewart

3
coi chừng giấy phép !!
harschware

cũng bị vấn đề tương tự được xác định bởi James Roper trong câu trả lời của Wolfgang Fahl - sử dụng toLowerCasemà không chỉ định một địa điểm
kbolino

9

Hãy thử điều này, đơn giản và dễ dàng

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

9

Lấy từ dự án này https://github.com/RishiGupta12/serial-cransication-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

Mã bên dưới hiển thị các giá trị mà bạn có thể nhận được từ API hệ thống, tất cả những điều bạn có thể nhận được thông qua API này.

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

Đáp án: -

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

Tôi thấy rằng hệ điều hành Utils từ Swingx thực hiện công việc.


2
Liên kết trên dường như bị phá vỡ, có thể là do các chi nhánh giới thiệu của SwingX; Bản phát hành 1.6 có tại đây: swingx.dev.java.net/source/browse/swingx/tags/SwingX-1-6/src/ Lỗi
David Moles

1
@David Nốt ruồi, cảm ơn. liên kết vẫn ổn khi tôi trả lời - Bây giờ tôi đã cập nhật nó với liên kết của bạn.
Richard Harrison

2
Phiên bản mới nhất có tại đây: java.net/projects/swingx/source/svn/content/trunk/swingx-core/
mẹo


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

4

Bạn chỉ có thể sử dụng phương thức sun.awt.OSInfo # getOSType ()


Đây nên là câu trả lời tốt nhất! Tôi chỉ kiểm tra xem ai đó đã đề cập đến vấn đề này ở đây chưa.
Martin Krajčírovič

Bất kỳ cách giải quyết nào cho việc này là 'API bị hạn chế'? Tôi muốn thử sử dụng cái này nhưng nó cho tôi cảnh báo đó trong Eclipse. Tôi có thể sử dụng jre cũ hơn (ví dụ jre1.8.0_171), nhưng 1,8 jres mới nhất có dấu được giới hạn.
Brian_Entei

4

Nếu bạn đang làm việc trong một môi trường nhạy cảm về bảo mật, thì vui lòng đọc qua.

Xin vui lòng không bao giờ tin tưởng một tài sản có được thông qua System#getProperty(String)chương trình con! Trên thực tế, hầu hết mọi tài sản bao gồm os.arch, os.nameos.versionkhông chỉ đọc như bạn mong đợi - thay vào đó, chúng thực sự hoàn toàn ngược lại.

Trước hết, bất kỳ mã nào có đủ quyền cho phép gọi System#setProperty(String, String)chương trình con đều có thể sửa đổi nghĩa đen được trả về theo ý muốn. Tuy nhiên, đó không nhất thiết là vấn đề chính ở đây, vì nó có thể được giải quyết thông qua việc sử dụng cái gọi là SecurityManager, như được mô tả chi tiết hơn ở đây .

Vấn đề thực tế là bất kỳ người dùng nào cũng có thể chỉnh sửa các thuộc tính này khi chạy JARcâu hỏi. Điều này có nghĩa là không có cách nào để xác định xem các tính chất này có thực sự chính xác hay không. Vì điều này, đây là một vài kiểm tra bổ sung để thử và tránh giả mạ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;
}

Một ý tưởng tốt khác là kiểm tra sự hiện diện của các thư mục cụ thể của hệ điều hành. Bất cứ cách tiếp cận nào bạn có thể thực hiện, hãy nhớ rằng ngôn ngữ Java được thụt lề là nền tảng chéo. Vậy tại sao bạn không thử làm điều tương tự?


3

Tôi thích câu trả lời của Wolfgang, chỉ vì tôi tin rằng những thứ như thế nên là ...

Vì vậy, tôi đã chia sẻ lại một chút cho bản thân mình và nghĩ sẽ chia sẻ nó :)

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

Có vẻ như "darwin" không bao giờ có thể được khớp bởi vì kiểm tra "win" sẽ khiến Windows bị trả về.
tvkanters

xem sửa trong câu trả lời ban đầu của tôi
Wolfgang Fahl

3
Xin chúc mừng, bạn đã thực hiện lại sun.awt.OSInfo # getOSType :)
Kirill Gamazkov

HHHHH ... một người tốt ... @Kirill Gamazkov Tôi đã không tìm thấy nó sau đó .. cảm ơn vì đã chỉ ra
TacB0sS

2

Mã này để hiển thị tất cả thông tin về loại hệ thống os, tên, thông tin java, v.v.

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

Trong lớp com.sun.jna.Pl platform, bạn có thể tìm thấy các phương thức tĩnh hữu ích như

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

và nhiều hơn nữa.

Nếu bạn sử dụng Maven, chỉ cần thêm phụ thuộc

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

Nếu không, chỉ cần tìm tệp jar thư viện jna (ví dụ: jna-5.2.0.jar) và thêm nó vào classpath.


1

Chỉ cần sử dụng com.sun.javafx.util.Utilsnhư dưới đây.

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

HOẶC DÙNG

boolean isWindows = OSInfo.getOSType().equals(OSInfo.OSType.WINDOWS);
       if (isWindows){
         // YOUR LOGIC HERE
       }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.