JAVA

Java中的System.getenv()和System.getProperty()

System.getenv()和System.getProperty()是Java种常用的两种读取环境配置信息的方法,它们都是java.lang.System类的方法,用途有相似之处,但我们在实际使用中,需要更加注意二者的区别。

1. System.getenv()


System.getenv()读取的是当前系统环境的环境变量。要深入理解环境变量的本质,需要对系统父子进程关系有更加清晰的认识。一般来说,子进程在创建时,会将父进程当时的环境变量复制一份,而父进程中之后发生的环境变量的变动,不会影响子进程中对应的环境变量。

当不传入参数时,System.getenv()的返回值为一个只读的Map,其中包括当前环境下所有环境变量。下面的例子中,我们将打印出这条语句执行时环境中所有的环境变量和它们对应的值,在 windows 中是 用户环境变量和系统环境变量的值,

System.getenv().forEach((key, value) -> {
    System.out.println(key + ":" + value);
});

注意:通过 System.getenv() 获取的 Map 是不支持修改的,为了有更深入的理解,我们熟悉下这块的代码

当不传入参数时,System.getenv()的返回值为一个只读Map,其中包括当前环境下所有环境变量。下面的例子中,我们将打印出这条语句执行时环境中所有的环境变量和它们对应的值。

public static java.util.Map<String,String> getenv() {
      // ......
      return ProcessEnvironment.getenv();
  }

ProcessEnvironment.getenv() 该方法的核心逻辑如下,从以下代码中可以看出,返回的 map 是通过Collections.unmodifiableMap() 处理的,因此,返回的map 是不能被修改的。

final class ProcessEnvironment extends HashMap<String,String>{
    private static final Map<String,String> theUnmodifiableEnvironment;
    static {
        theEnvironment  = new ProcessEnvironment();
		theUnmodifiableEnvironment
           	 = Collections.unmodifiableMap(theEnvironment);
    }
    // Only for use by System.getenv()
    static Map<String,String> getenv() {
        return theUnmodifiableEnvironment;
    }
}

一般我们在程序中使用时,一般不会获取全部的系统环境变量,因而可以通过 System.getEnv(key) 获取对应环境变量的值。

public static String getenv(String name) {
     // .....
     return ProcessEnvironment.getenv(name);
 }

我们知道有:System.getenv(String key);
那么如何实现System.setenv()?

尝试修改这一Map的内容将会抛出UnsupportedOperationException异常。

System.getenv()也可以接受单个String作为输入参数,表示需要获取的环境变量名。若在当前环境中存在这一变量,则以String方式返回其对应的值,否则返回null。因此,在使用System.getenv()时,需要注意处理返回null的情形,否则将很可能会导致NullPointerException异常。

2. System.getProperty()


通上,通过 System.getProperty(key)获取单个变量值,通过System.getPropertys() 获取所有 JVM 环境变量值。如下

System.getProperties().forEach((k,v) -> {
    System.out.println(k + "=" + v);
});

这里列出一些常见的

// classpath
sun.boot.class.path=C:\Program Files\Java\jdk1.8.0_131\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_131\jre\lib\rt.jar;....
java.library.path=C:\Program Files\Java\jdk1.8.0_131\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;
file.separator=\
sun.jnu.encoding=GBK
java.version=1.8.0_131
java.vm.info=mixed mode

当我们通过 启动JVM时,可以通过 -D 设置JVM 环境变量值,在我们的程序中我们也可以通过,System.setProperty(key,value) 设置JVM 环境变量,该值在整个JVM 间是共享的。

总结


Java提供了System类的静态方法getenv()和getProperty()用于返回系统相关的变量与属性,getenv方法返回的变量大多于系统相关,getProperty方法返回的变量大多与java程序有关。

通过 System.getenv() 和 getProperty() 可以简化我们的有些配置,相比于 xml 等配置文件,这种方式更轻量,如果我们的程序中没有配置文件,但想使某一两项功能实现可配置,通过System.getenv() 和 getProperty()可以非常容易的实现。

经过上述比较,可以将System.getenv()System.getProperty()的区别归纳为以下几点:

  • System.getProperty()所获取的Property是可读可写的,而System.getenv()获取的环境变量只可读不可写。
  • System.getProperty()要求我们提供默认项,而使用System.getenv()时需要考虑null的情况
  • Property只对Java程序有影响,而环境变量会影响整个平台下的所有应有程序