平常在項目中會分模塊進行開發,讀寫文件時使用的都是絕對路徑,測試程序也是使用idea直接執行程序。在學習jetty源碼時,由於需要在start模塊中啟動項目,但需要動態加載依賴的其他模塊,此時代碼中使用的是相對路徑,在使用idea啟動程序的時候,可以正常執行,但在命令行中使用java命令啟動程序時,總是會報java.lang.ClassNotFoundException,分析原因見下:
1. 打開idea的run配置:
雖然是在start模塊中啟動程序,但idea會自動將運行時的程序根路徑設置為working directory中設置的目錄,此時項目中使用的相對路徑就是依據working directory路徑的相對路徑(此處是猜測,具體驗證可以通過修改working directory內容來驗證)
2. 使用java命令執行時,由於沒有設置程序運行時的根路徑,此時就會將當前main方法所在的類所處的目錄設置為跟路徑,代碼中再使用相對路徑時,就是根據main方法所在的類所在的目錄生成的路徑
根據以上猜測和分析,解決此問題的根本就是找到如何設置程序運行時的根目錄
----- 分隔線 ----
分析java源碼:
File類:
//獲取文件絕對路徑方法
public String getAbsolutePath() { return fs.resolve(this);//FileSystem.resolve()方法 }
根據操作系統不同,使用的FileSystem實現類不一樣,我的是mac系統,使用的是UnixFileSystem類:
1 public String resolve(File f) { 2 if (isAbsolute(f)) return f.getPath(); 3 return resolve(System.getProperty("user.dir"), f.getPath()); 4 }
可以發現java源碼中使用的是System.getProperty("user.dir")來設置程序運行的跟目錄的,那么就可以通過此設置解決這個問題:
1 System.setProperty("user.dir", "/workspace/code/git/jetty.project");
總結:通過修改系統屬性user.dir,使用java命令也可以通過jetty源碼正常啟動了,此時可以猜測idea是否也是通過將working directory設置到user.dir屬性來實現的呢。
---- 少百度,多看源碼