從new File("")到JDK源碼

1. 概述

今天在項(xiàng)目中看到下面兩行代碼,看注釋說(shuō)是獲取當(dāng)前工作路徑,之前也沒(méi)有用過(guò)這種用法,比較好奇還能這樣用,所以研究了一下源碼。

//獲取當(dāng)前工作路徑
File file = new File("");
String currentWorkDirectory = file.getAbsolutePath();

2. new File("")解析

首先,new File()是創(chuàng)建一個(gè)虛擬的文件(File)對(duì)象,通過(guò)這個(gè)對(duì)象可以調(diào)用很多方法來(lái)獲取文件和目錄的相關(guān)信息。以下列出一些常用方法:

2.1 File的常用方法

方法簽名 作用
boolean delete() 刪除文件或目錄
void deleteOnExit() 在jvm退出時(shí)刪除文件或目錄
boolean createNewFile() 當(dāng)以這個(gè)文件名命名的文件不存在時(shí),創(chuàng)建一個(gè)新的空文件
boolean exists() 判斷文件或目錄是否存在
String getAbsolutePath() 獲取File對(duì)象的絕對(duì)路徑
String getName() 獲取文件或目錄名稱(chēng)
File getParentFile() 獲取父File對(duì)象
String getPath() 獲取File對(duì)象創(chuàng)建時(shí)傳入的pathname參數(shù)
boolean isDirectory() 判斷是否是目錄
File[] listFiles() 列出當(dāng)前目錄下的所有文件
boolean mkdir() 創(chuàng)建單個(gè)目錄
boolean mkdirs() 創(chuàng)建多級(jí)目錄

2.2 new File("")做了什么

我們先來(lái)看看源碼是怎么描述的:

image.png

其中注釋的意思是:將指定的文件路徑轉(zhuǎn)換為一個(gè)絕對(duì)路徑,然后創(chuàng)建一個(gè)新的File實(shí)例。如果給定的文件路徑參數(shù)為空值,則返回空的絕對(duì)路徑名。

官方的注釋比較難理解,通俗的將就是,當(dāng)我傳入一個(gè)相對(duì)路徑就會(huì)轉(zhuǎn)換為絕對(duì)路徑,當(dāng)我傳入一個(gè)""參數(shù)時(shí),就只有一個(gè)絕對(duì)路徑。那么這個(gè)絕對(duì)路徑代表什么含義呢?

2.3 深入源碼看File絕對(duì)路徑(abstract pathname)的含義

2.3.1 File.getAbsolutePath()方法

其實(shí)我們可以看到new File(String pathname)這個(gè)構(gòu)造方法只設(shè)置了相對(duì)路徑和解析相對(duì)路徑的長(zhǎng)度。并沒(méi)有有關(guān)絕對(duì)路徑的操作。那么究竟是在哪里設(shè)置的絕對(duì)路徑呢?這個(gè)就涉及到getAbsolutePath()方法了。

下面我們看一下getAbsolutePath()方法做了什么:

image.png

從注釋可以看出,如果在new File()的時(shí)候傳入的pathname已經(jīng)是絕對(duì)路徑的話(huà),那么這個(gè)方法的返回就和getPath()一樣,如果傳入的是空字符串的話(huà),那么就返回當(dāng)前目錄的路徑,通過(guò)系統(tǒng)屬性u(píng)ser.dir獲取。

2.3.2 WinNTFileSystem.resolve()方法

那么我們繼續(xù)往下看:

image.png

點(diǎn)進(jìn)去resolve()方法可以看到返回值實(shí)際是從getUserPath()這個(gè)方法獲取的。

image.png

2.3.3 WinNTFileSystem.getUserPath()方法

getUserPath()方法調(diào)用了System.getProperty("user.dir")方法來(lái)獲取user.dir這個(gè)key的配置。再往里面看user.dir的值其實(shí)是從props這個(gè)Properties對(duì)象中獲取的。

image.png

2.3.4 System.setProperties(props)方法

那props又是從哪里拿到這個(gè)值的呢?我們接著往下看:

在System類(lèi)里面對(duì)著props這個(gè)屬性用ctrl+鼠標(biāo)左鍵查找props在哪幾個(gè)地方使用了??梢钥吹接幸粋€(gè)setProperties(Properties props)方法。再對(duì)著setProperties這個(gè)方法使用ctrl+鼠標(biāo)左鍵查找。

image.png

2.3.5 Process.main()方法

在com.sun.org.apache.xalan.internal.xslt.Process的main方法里面我們可以看到,執(zhí)行了System.setProperties(props),而System.setProperties(props)調(diào)用了本地方法private static native Properties initProperties(Properties props)對(duì)props進(jìn)行初始化。

image.png

2.3.6 System.initProperties(Properties props)本地方法

image.png

到這里的話(huà),其實(shí)java源代碼已經(jīng)結(jié)束了,總結(jié)來(lái)說(shuō)就是jvm在啟動(dòng)的時(shí)候調(diào)用了System類(lèi)的private static native Properties initProperties(Properties props)本地方法對(duì)props屬性進(jìn)行初始化,設(shè)置了user.dir的值。

這時(shí)可能還有些好奇寶寶不甘心,為什么調(diào)用了這個(gè)本地方法就可以獲取user.dir的值,那么我們就來(lái)研究一下openjdk的c語(yǔ)言源碼吧。

2.4 深入openjdk源碼

我們從github上搜索到openjdk的源碼倉(cāng)庫(kù),隨便找一個(gè)java8的tag來(lái)研究initProperties()這個(gè)本地方法到底做了什么。

github的openjdk代碼倉(cāng)庫(kù)

  1. 首先我們找到j(luò)dk/src/share/native/java/lang目錄下面的System.c文件。在里面搜索一下initProperties,可以看到有一個(gè)Java_java_lang_System_initProperties方法。
image.png
  1. 接著我們?cè)谶@個(gè)方法里面搜索user_dir,可以看到值是從一個(gè)sprops指針中獲取的,而sprops從上一張圖可以看出是從GetJavaProperties(env)這個(gè)方法獲取的值。
image.png
  1. 那我們ctrl+shift+F全局搜索一下GetJavaProperties這個(gè)方法。可以看到j(luò)dk/src/windows/native/java/lang/java_props_md.c文件中有這個(gè)方法,從文件路徑可以看出這個(gè)文件是windows系統(tǒng)下執(zhí)行的。
image.png
  1. 接著在這個(gè)方法里面搜索user_dir,可以看到user_dir實(shí)際是從GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR), buf)方法里面獲取值的。GetCurrentDirectoryW這個(gè)方法就是windows的系統(tǒng)函數(shù),用來(lái)獲取當(dāng)前工作目錄。
image.png

到這里jdk源碼解析就結(jié)束了,可以看到在windows系統(tǒng)下是調(diào)用了它的系統(tǒng)函數(shù)獲取當(dāng)前工作目錄。

備注:_wcsdup(buf)方法是c語(yǔ)言的庫(kù)函數(shù),作用是分配一塊新的空間,然后從buf數(shù)組里面獲取值賦值給新創(chuàng)建的空間。

3. 總結(jié)

  1. 絕對(duì)路徑是什么:當(dāng)前工作目錄,就是當(dāng)前項(xiàng)目的根路徑
  2. 使用new File("")創(chuàng)建File對(duì)象時(shí),絕對(duì)路徑其實(shí)是getAbsolutePath()方法獲取的,new File("")只是設(shè)置了path=""
  3. System.props這個(gè)屬性其實(shí)包含了很多值,如:java.version、user.home等等,可以看源碼中的注釋
  4. 通過(guò)System.getProperty(key)可以獲取系統(tǒng)的一些配置信息
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • File類(lèi)介紹 File是java.io包下面的一個(gè)類(lèi),代表與平臺(tái)無(wú)關(guān)的文件或者目錄。JAVA中,無(wú)論文件還是目錄...
    少帥yangjie閱讀 408評(píng)論 0 1
  • 本文簡(jiǎn)單羅列 File類(lèi)構(gòu)造方法 File類(lèi)常用方法 在Java語(yǔ)言的java.io包中,由File類(lèi)提供了描述文...
    stoneyang94閱讀 544評(píng)論 0 0
  • File 存儲(chǔ)在變量,數(shù)組,對(duì)象的數(shù)據(jù)都是存儲(chǔ)在內(nèi)存中,一旦程序關(guān)閉,這些數(shù)據(jù)就會(huì)丟失。為了能夠永久保存程序運(yùn)行過(guò)...
    獅_子歌歌閱讀 425評(píng)論 0 1
  • File類(lèi)(File類(lèi)的概述和構(gòu)造方法) A:File類(lèi)的概述File更應(yīng)該叫做一個(gè)路徑文件路徑或者文件夾路徑路徑...
    厲害了我的彭閱讀 796評(píng)論 0 3
  • java項(xiàng)目動(dòng)態(tài)配置常量和peiconfig.properties配置使用詳解 點(diǎn)擊:2 Java工程中配置信息一...
    zhoulujun閱讀 5,080評(píng)論 0 1

友情鏈接更多精彩內(nèi)容