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

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM