java环境变量(env)和系统属性(property)

源起

最近看log4j2源码发现PropertiesUtil类被用于获取配置信息(封装为PropertySource类),可以用于获取日志工厂的类名和配置工厂的类名等属性,log4j2默认为我们提供了以下实现类

PropertiesPropertySource:加载classpath:log4j2.component.properties配置文件,权重0

SystemPropertiesPropertySource:获取System.getProperties()属性,权重100

EnvironmentPropertySource:获取System.getenv()属性,权重-100

log4j2分别为这三个类指定了权重,并通过TreeSet指定比较器按照权重升序存放加载后的PropertySource配置类,最后会循环配置列表,按照指定的key获取属性。这样相同的key,权重高的配置就会覆盖权重低的配置。按照优先级看,相同的属性System.getProperties()>System.getenv(),那么这两个属性到底有什么区别,为何要指定getProperties()>getenv()

探究

当程序中需要使用与操作系统相关的变量(文件分隔符、换行符等)时,java提供了System类的静态方法getProperties()和getenv(),用于获取系统相关的配置属性。这两个方法都能将系统相关的配置属性以key-value的形式传递给java进程

getProperties()

引用jdk中的注释说明Determines the current system properties.:确定当前系统的属性。我们的java程序运行在jvm虚拟机之上,并不和操作系统直接交互,所以这里的当前系统指的并不是我们的操作系统,而是jvm虚拟机,实际获取的是jvm虚拟机的系统属性。

  • 查看jvm虚拟机系统属性

执行%java_home%/bin/jvisualvm.exe,在本地->VisualVM->系统属性中可以查看当前jvm虚拟机的系统属性

 

 

 

  • 执行getProperties()方法
    public static void main(String[] args) {

        Properties properties = System.getProperties();
        properties.forEach(new BiConsumer<Object, Object>() {
            @Override
            public void accept(Object o, Object o2) {
                System.out.println("property:" + o + "=" + o2);
            }
        });
    }

二者对比可以发现jvm虚拟机中的系统属性包含getProperties()的结果,引用jdk中的注释说明This set of system properties always includes values* for the following keys:,该方法在获取系统属性的时候指定了需要的keys列表

  • 可用的系统属性汇总
java.version Java :运行时环境版本
java.vendor Java :运行时环境供应商
java.vendor.url :Java供应商的 URL
java.home &nbsp;&nbsp;:Java安装目录
java.vm.specification.version: Java虚拟机规范版本
java.vm.specification.vendor :Java虚拟机规范供应商
java.vm.specification.name &nbsp; :Java虚拟机规范名称
java.vm.version :Java虚拟机实现版本
java.vm.vendor :Java虚拟机实现供应商
java.vm.name&nbsp; :Java虚拟机实现名称
java.specification.version:Java运行时环境规范版本
java.specification.vendor:Java运行时环境规范供应商
java.specification.name :Java运行时环境规范名称
java.class.version :Java类格式版本号
java.class.path :Java类路径
java.library.path  :加载库时搜索的路径列表
java.io.tmpdir  :默认的临时文件路径
java.compiler  :要使用的 JIT编译器的名称
java.ext.dirs :一个或多个扩展目录的路径
os.name :操作系统的名称
os.arch  :操作系统的架构
os.version  :操作系统的版本
file.separator :文件分隔符
path.separator :路径分隔符
line.separator :行分隔符
user.name :用户的账户名称
user.home :用户的主目录
user.dir:用户的当前工作目录

getenv()

引用jdk中的注释说明Returns an unmodifiable string map view of the current system environment.:获取不可变的当前系统的环境变量,返回字符串类型的Map。这里的环境包括系统所在环境(操作系统环境变量)和系统自身环境(用户环境变量)。

不同操作系统设置环境变量方式不同,举例,windows使用控制面板中系统程序,而Unix使用shell脚本。当创建一个进程时,缺省其继承其父进程的环境变量副本。

配置jdk的过程就是给操作系统增加环境变量,操作系统环境变量的值可以被所有运行在操作系统上的jvm虚拟机中的java程序获取

注意:这里返回的Map实际的实现类是UnmodifiableMap,是一个只读的视图。

  • 可用的环境变量汇总
USERPROFILE        :用户目录
USERDNSDOMAIN      :用户域
PATHEXT            :可执行后缀
JAVA_HOME          :Java安装目录
TEMP               :用户临时文件目录
SystemDrive        :系统盘符
ProgramFiles       :默认程序目录
USERDOMAIN         :帐户的域的名称
ALLUSERSPROFILE    :用户公共目录
SESSIONNAME        :Session名称
TMP                :临时目录
Path               :path环境变量
CLASSPATH          :classpath环境变量
PROCESSOR_ARCHITECTURE :处理器体系结构
OS                     :操作系统类型
PROCESSOR_LEVEL    :处理级别
COMPUTERNAME       :计算机名
Windir             :系统安装目录
SystemRoot         :系统启动目录
USERNAME           :用户名
ComSpec            :命令行解释器可执行程序的准确路径
APPDATA            :应用程序数据目录

应用

我们可以通过以下方式设置环境变量和系统属性

  • 环境变量

环境变量没有提供set方法,程序运行状态无法添加或修改,只能预先设置(设置方法参考jdk)

idea中可以通过Edit Configurations…->Environment variables:log_dir=/tmp/log进行设置

 

 

 

  • 系统属性

运行时更新系统属性, 可使用System.setProperty()方法:

System.setProperty("log_dir","/tmp/log");

启动时可以通过命令行方式传参方式将属性配置传递给应用程序

java -jar xxx.jar -Dlog_dir="/tmp/log"

idea中可以通过Edit Configurations…->VM options:-Dlog_dir=/tmp/log进行设置

 

 

 

 

总结

  • 环境变量是操作系统环境变量的不可变副本,只能预先设置,程序启动后不可修改
  • 作用范围不同,环境变量是是操作系统级的,对运行在操作系统上的所有应用都有效;系统属性只对当前jvm虚拟机有效

系统属性与环境变量都是名称与值之间的映射。两种机制都可以将用户定义的信息传递给java进程。

环境变量产生的更多的是全局效应,他们不仅对java子进程可见,而且对于定义它们的所有子进程都是可见的。

程序中尽可能使用系统属性,而环境变量应该在全局范围需要时才使用

回首掏

回到最初的问题,log4j2为何要指定getProperties()>getenv()?原因大概就是环境变量的作用范围要大于系统属性,为了实现个性化配置覆盖通用配置吧。

目前主流的框架都会使用环境变量和系统属性进行配置管理,理解他们对后续框架的学习至关重要。

 

转载:https://blog.csdn.net/dcr782195101/article/details/122000536

 

 

 

posted @ 2022-04-14 11:44  迷走神经  阅读(2444)  评论(0编辑  收藏  举报