admin 管理员组

文章数量: 887006

在Java开发过程中,有时候需要根据操作系统的类型,来选择执行不同的脚本或加载不同的动态库,比如 Window下的脚本是 .bat 文件,而 Linux 下的脚本是 .sh 文件,还有 Windows 下的动态库是 .dll 文件,而 Linux 下是 .so 文件。

如果想要知道当前操作系统的类型,可以通过系统属性 os.name 来判断,而系统属性具体是通过 System.getProperty(os.name) 方法获取的,下面先来分析一下 System 类中的相关源码。

1、System类源码分析

System 类位于 java.lang 包下,它是一个 final 类,也就表示该类是不能被继承的,它的类定义如下:

public final class System {
    
    /** Don't let anyone instantiate this class */
    private System() {
    }
}

其中构造函数是私有的,不能被实例化。

获取系统属性的方法是 getProperty(),该方法有两个重载方法,如下:

  • public static String getProperty(String key):其中参数 key 就是属性名;
  • public static String getProperty(String key, String def):参数 key 就是属性名,而参数 def 表示默认值,当指定属性 key 没有值时,使用默认值 def 替代。

下面分别看看这两个方法的源码:

(1)getProperty(String key)

public static String getProperty(String key) {
    // 检查属性名
    checkKey(key);
    // 获取安全管理器
    SecurityManager sm = getSecurityManager();
    if (sm != null) {
        // 检查属性访问权限
        sm.checkPropertyAccess(key);
    }

    // 获取并返回属性值
    return props.getProperty(key);
}

获取系统属性,通常会经历三个步骤:

  • 检查属性名是否为空
  • 检查属性访问权限
  • 获取属性值

其中 checkKey() 方法源码如下:

private static void checkKey(String key) {
    if (key == null) {
        throw new NullPointerException("key can't be null");
    }
    if (key.equals("")) {
        throw new IllegalArgumentException("key can't be empty");
    }
}

该方法主要判断属性名是否为 null 或者为空字符串,如果为 null ,则会抛出 NullPointerException 异常,如果为空字符串,则会抛出 IllegalArgumentException 异常。

SecurityManager 是安全管理器,用于实现安全策略的类,检查应用程序是否具有某些操作的权限,最终会调用 AccessControlContext 类的 checkPermission() 方法,如果应用程序没有操作权限,则会抛出 AccessControlException 异常。

最终属性值的获取是通过 Properties 类的 getProperty() 方法获取的,所有的系统属性都会保存在 Properties 实例中,由JVM进行初始化,其定义如下:

private static Properties props;
private static native Properties initProperties(Properties props);

initProperties() 方法又是在 initializeSystemClass() 方法中调用的,源码如下:

private static void initializeSystemClass() {
    props = new Properties();
    initProperties(props);  // initialized by the VM
    //....
}

关于 Properties 类的 getProperty() 方法定义如下:

public String getProperty(String key) {
    Object oval = super.get(key);
    String sval = (oval instanceof String) ? (String)oval : null;
    return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;
}

(2)getProperty(String key, String def)

public static String getProperty(String key, String def) {
    checkKey(key);
    SecurityManager sm = getSecurityManager();
    if (sm != null) {
        sm.checkPropertyAccess(key);
    }

    return props.getProperty(key, def);
}

该方法和上一个方法的区别在于它可以设置一个默认值,当属性值不存在时,则会使用默认值替代,调用的是 PropertiesgetProperty(String key, String defaultValue) 方法,其定义如下:

public String getProperty(String key, String defaultValue) {
    // 首先获取属性值
    String val = getProperty(key);
    // 如果属性值为 null,则返回默认值
    return (val == null) ? defaultValue : val;
}

2、代码实现

package com.magic.system;

public class SystemUtils {

    /**
     * 判断操作系统是否是 Windows
     *
     * @return true:操作系统是 Windows
     *         false:其它操作系统
     */
    public static boolean isWindows() {
        String osName = getOsName();

        return osName != null && osName.startsWith("Windows");
    }

    /**
     * 判断操作系统是否是 MacOS
     *
     * @return true:操作系统是 MacOS
     *         false:其它操作系统
     */
    public static boolean isMacOs() {
        String osName = getOsName();

        return osName != null && osName.startsWith("Mac");
    }

    /**
     * 判断操作系统是否是 Linux
     *
     * @return true:操作系统是 Linux
     *         false:其它操作系统
     */
    public static boolean isLinux() {
        String osName = getOsName();

        return (osName != null && osName.startsWith("Linux")) || (!isWindows() && !isMacOs());
    }

    /**
     * 获取操作系统名称
     * @return os.name 属性值
     */
    public static String getOsName() {
        return System.getProperty("os.name");
    }
}

3、测试验证

测试验证代码如下:

public static void main(String[] args) {
    System.out.println("os.name : " + getOsName());

    System.out.println("isWindows : " + isWindows());
    System.out.println("isLinux : " + isLinux());
    System.out.println("isMacOs : " + isMacOs());
}

在 Windows 10 系统环境下运行,输出结果如下:

os.name : Windows 10
isWindows : true
isLinux : false
isMacOs : false

在 CentOS 7 系统环境下运行,输出结果如下:

os.name : Linux
isWindows : false
isLinux : true
isMacOs : false

本文标签: 操作系统 代码 java macOS Linux