每個 JVM 進程啟動時都會綁定一個工作目錄,預設為啟動命令的當前目錄。所有相對路徑(new File("data.txt")、ClassLoader.getResource("") 等)均以此為基準解析。
// 獲取(標準 API)
String cwd = System.getProperty("user.dir"); // 唯一標準方式
// 嘗試修改(無效!)
System.setProperty("user.dir", "/new/path"); // 僅修改 Properties 物件,不影響底層 native 狀態
警告:user.dir是 JVM 內部 native 狀態,System.setProperty無法真正改變進程工作目錄,甚至可能導致多線程環境下路徑解析混亂(JDK 1.4 確認存在此 Bug)。
/home/user/project/binC:\project\bin當資源檔(配置、腳本、依賴庫)不在工作目錄下,且不想寫死絕對路徑時,有兩種方案:
File config = new File("/opt/app/conf/config.properties"); // 部署遷移需改代碼
| JDK 版本 | API | 關鍵參數 |
|---|---|---|
| 1.4 | Runtime.exec(cmd, envp, dir) |
dir 為 File 物件,指定子進程工作目錄 |
| 1.5+ | ProcessBuilder |
pb.directory(new File("/target/path")),功能更豐富、鏈式調用 |
// JDK 1.5+ 標準寫法
ProcessBuilder pb = new ProcessBuilder("myScript.sh", "arg1");
pb.directory(new File("/opt/app/scripts")); // 設定子進程工作目錄
Process process = pb.start();
// 處理輸出流、錯誤流、等待結束...
ClassLoader.getResourceAsStream() 或 Spring ResourceLoader。directory()、環境變數、重導向輸出流。WORKDIR 指令固化工作目錄,消除環境差異。JVM 工作目錄在進程啟動時確定,不可運行時修改。正確姿勢是:業務代碼拋棄相對路徑,外部進程調用用 ProcessBuilder 隔離工作目錄,容器層面用 WORKDIR 固化。