Java로 운영 체제를 프로그래밍 방식으로 결정하려면 어떻게합니까?


526

Java 프로그램이 프로그래밍 방식으로 실행중인 호스트의 운영 체제를 결정하고 싶습니다 (예 : Windows 또는 Unix 플랫폼인지 여부에 따라 다른 속성을로드 할 수 있기를 원합니다). 100 % 신뢰도로이를 수행하는 가장 안전한 방법은 무엇입니까?

답변:


617

당신이 사용할 수있는:

System.getProperty("os.name")

추신 :이 코드가 유용 할 것입니다 :

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

Java 구현에서 제공하는 모든 속성을 인쇄하기 만하면됩니다. 속성을 통해 Java 환경에 대한 정보를 얻을 수 있습니다. :-)


6
나는 사용 Windows 10하고 있지만 아직 os.name나에게 준다 Windows 8.1. 왜 그런 겁니까? 이것은 어디에서 오는가?
Brian



82

2008 년 10 월 :

정적 변수로 캐시하는 것이 좋습니다.

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
}

이렇게하면 Os를 요청할 때마다 응용 프로그램 수명 동안 속성을 두 번 이상 가져 오지 않습니다.


2016 년 2 월 : 7 년 이상 후 :

Windows 10에는 버그가 있습니다 (원래 답변 당시에는 존재하지 않았 음).
" Windows 10 용 Java의"os.name "을 참조하십시오 . "


5
OAOO (한 번만 한 번)를 기준으로 getOSName 함수에 동의합니다. 그러나 캐싱은 해시 조회 속도를 고려할 때 완전히 중복됩니다.
Chris Jester-Young

6
완전히 중복되는 것은 다소 거칠 수 있으며 해시 조회는 참조에 액세스하는 것보다 비쌉니다. 그것은 모두 상황에 달려 있습니다.
Craig Day

2
좋은 점 ... 나쁜 습관이라고 생각되면 자유롭게 투표하십시오.)
VonC

5
이 답변을 다시 읽습니다. 캐시하려는 isWindows경우 isUnix, 등 의 값을 캐시하십시오 . 이렇게하면 문자열 비교 시간도 절약됩니다.
Chris Jester-Young

2
@ 브라이언 트루. 나는 가장 오래된 답변을 참조하기 위해이 매우 오래된 답변을 편집했습니다.
VonC 2019

44

위 답변의 일부 링크가 끊어진 것 같습니다. 아래 코드에 현재 소스 코드에 대한 포인터를 추가했으며 결과를 평가할 때 switch 문을 사용할 수 있도록 열거 형으로 검사를 처리하는 방법을 제공합니다.

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

도우미 클래스는 다음과 같습니다.

/**
 * 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)은 (OS.indexOf ( "win")> = 0) 이후이기 때문에 절대 적용 할 수 없습니다.
William

14
위의 코드 는 로캘에 민감한 toLowerCase ()를 사용하기 때문에 로캘 문제 있을 있습니다. 특히 터키에서 i를 소문자 / 대문자로 변환 할 때 중요한 점은 터키에서 소문자로 구분되지 않은 i (ı)가되고 i는 대문자로 구분 된 i (İ)가되기 때문입니다. 따라서 "WINDOWS".toLowerCase (). indexOf ( "win")은 터키에서 -1을 반환합니다. 특정 언어의 소문자를 수행 할 때는 항상 로케일을 전달하십시오. 즉 "WINDOWS".toLowerCase (Locale.ENGLISH) .indexOf ( "win")는 터키에서 작동합니다.
James Roper

@JamesRoper-고맙습니다.
Wolfgang Fahl

7
OS.contains (...)
Grigory Kislin

42

다음 JavaFX 클래스에는 현재 OS (isWindows (), isLinux () ...)를 결정하는 정적 메소드가 있습니다.

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

예:

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

이것은 더 높아야한다
서식지 2

3
"com / sun / javafx / *"에 대한 액세스는 권장하지 않습니다 (JDK 1.8.0_121에서 확인).
Michael Marton

1
@MichaelMarton 당신의 진술에 대한 참조가 있습니까?
Hummeling Engineering BV

@ HummelingEngineeringBV : 내 측면에서 실수 한 것 같습니다. Eclipse Neon 4.6.3으로 작업 중이며 "Java Build Path"에 몇 가지 "Discouraged : com / sun / javafx / **"경고가 표시됩니다. 그러나 내가 알았 듯이 이것은 일식 버그 및 / 또는 기능입니다 ( link 참조 ).
Michael Marton

2
한 번 더 수정해야합니다. Java 9/10 이상부터 몇 가지 "com.sun. *"패키지 / API가 제거 될 예정입니다. 자세한 내용은 이 링크 를 확인하십시오 . 우리는 이러한 패키지 중 일부를 사용하기 때문에 실제로 이것을 우연히 발견했습니다. 이클립스 4.8 / JDK 10으로 마이그레이션 할 때, 이제 누락 된 참조로 인해 이들 및 기타 여러 컴파일러 오류를 수정해야합니다.
Michael Marton

16

TL; DR

OS에 액세스하려면 : System.getProperty("os.name").


그러나 유틸리티 클래스를 작성하여 재사용 가능하게 만드십시오! 여러 통화에서 훨씬 빠릅니다. 깨끗하고 깨끗하며 빠릅니다!

이러한 유틸리티 함수에 대한 Util 클래스를 작성하십시오. 그런 다음 각 운영 체제 유형에 대한 공개 열거 형을 만듭니다.

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

이제 다음과 같이 모든 클래스에서 클래스를 쉽게 호출 할 수 있습니다.

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

그게 다야!


2
오픈 소스 프로젝트 ( github.com/openhab/openhab-addons ) 에서이 코드를 사용하고 싶습니다. 괜찮습니까?
Consti P

예, 자유롭게 사용하십시오.
Memin

13

달성하려는 작은 예는 아마도 class아래의 것과 비슷할 것입니다 .

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

이 특정 구현은 매우 안정적이며 보편적으로 적용 가능해야합니다. 원하는대로 복사하여 붙여 넣기 만하면 class됩니다.


10

오픈 소스 프로젝트가 이와 같은 작업을 수행하는 방법에 관심이 있다면이 정크를 처리하는 Terracotta 클래스 (Os.java)를 확인할 수 있습니다.

그리고 JVM 버전 (Vm.java 및 VmVersion.java)을 처리하는 비슷한 클래스를 여기에서 볼 수 있습니다.


2
테라코타 클래스는 매우 포괄적입니다!
Stewart

3
라이센스를 조심하십시오 !!
harschware

또한 James Roper가 Wolfgang Fahl의 답변 에서 확인한 것과 동일한 문제 toLowerCase가 있습니다. 로캘을 지정하지 않고 사용
kbolino

9

간단하고 쉬운 이것을 시도하십시오

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

9

이 프로젝트에서 가져온 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 {
}

8

아래 코드는 시스템 API에서 얻을 수있는 값과이 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"));
    }
}

대답:-

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

SwingxOS Utils 가 작업을 수행 한다는 것을 알았 습니다.


2
아마도 SwingX가 브랜치를 도입했기 때문에 위의 링크가 끊어진 것 같습니다. 1.6 릴리스는 다음과 같습니다. swingx.dev.java.net/source/browse/swingx/tags/SwingX-1-6/src/…
David Moles

1
@David Moles, 감사합니다. 내가 대답했을 때 링크가 정상이었습니다. 이제 귀하의 링크로 업데이트했습니다.
Richard Harrison




4

sun.awt.OSInfo # getOSType () 메소드를 사용할 수 있습니다


이것이 가장 좋은 대답이어야합니다! 누군가가 이미 이것을 언급했는지 확인하고있었습니다.
Martin Krajčírovič

이 '제한된 API'에 대한 해결 방법이 있습니까? 이것을 사용 해보고 싶지만 Eclipse에서 경고를줍니다. 더 오래된 jre (예 : jre1.8.0_171)를 사용할 수 있지만 최신 1.8 jres에는 제한으로 표시되어 있습니다.
Brian_Entei

4

보안에 민감한 환경에서 작업하는 경우이 내용을 읽어보십시오.

System#getProperty(String)서브 루틴을 통해 얻은 자산을 절대 신뢰하지 마십시오 ! 사실, 거의 포함한 모든 재산 os.arch, os.nameos.version 당신이 기대하는 것 같은 읽기 전용되지 않습니다 - 대신, 그들은 실제로는 정반대입니다.

우선, System#setProperty(String, String)서브 루틴 을 호출 할 수있는 충분한 권한이있는 코드 는 반환 된 리터럴을 마음대로 수정할 수 있습니다. 이 소위의 사용을 통해 해결 될 수있는 그러나, 여기 반드시 기본 문제 아니에요 SecurityManager을보다 상세하게 설명 된 바와 같이, 여기 .

실제 문제는 모든 사용자가 문제를 실행할 때 이러한 속성을 편집 할 수 있다는 것 JAR입니다. 즉 , 이러한 속성이 실제로 정확한지 확인할 방법없습니다 . 이로 인해 다음은 변조 방지를위한 몇 가지 추가 검사입니다.

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

또 다른 좋은 아이디어는 운영 체제 별 디렉토리가 있는지 확인하는 것입니다. 어떤 접근 방식을 사용하든 Java 언어는 크로스 플랫폼이 될 수 있습니다. 그렇다면 왜 그렇게하려고하지 않습니까?


3

볼프강의 대답이 마음에 들었습니다.

그래서 나는 그것을 나 자신을 위해 약간 표현했고 그것을 공유하려고 생각했습니다 :)

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

"win"을 확인하면 이미 Windows가 반환되므로 "darwin"을 일치시킬 수없는 것 같습니다.
tvkanters

내 원래 답변의 수정 사항 참조
Wolfgang Fahl

3
축하합니다. sun.awt.OSInfo # getOSType :)
Kirill Gamazkov가

HHHHH ... 좋은 하나 ... @Kirill Gamazkov 그때는 찾지 못했습니다. 지적 해 주셔서 감사합니다
TacB0sS

2

이 시스템 코드는 시스템 운영 체제 유형, 이름, Java 정보 등에 대한 모든 정보를 표시합니다.

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

com.sun.jna.Platform 클래스에서 다음과 같은 유용한 정적 메소드를 찾을 수 있습니다

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

그리고 훨씬 더.

Maven을 사용하는 경우 종속성을 추가하십시오.

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

그렇지 않으면 jna 라이브러리 jar 파일 (예 : jna-5.2.0.jar)을 찾아 classpath에 추가하십시오.


1

com.sun.javafx.util.Utils아래와 같이 사용하십시오 .

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

또는 사용

boolean isWindows = OSInfo.getOSType().equals(OSInfo.OSType.WINDOWS);
       if (isWindows){
         // YOUR LOGIC HERE
       }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.