問題現象
將 Spring 4.0.5 源碼(spring-webmvc、spring-web)作為專案模組引入以便調試,啟動專案報錯:RequestMappingHandlerAdapter 實例化 ServletRequestMethodArgumentResolver 時找不到 java.time.ZoneId。環境為 JDK 7,但源碼已使用 JDK 8 新 API。
根本原因
- Spring 4.0 起原始碼已支援 JDK 8 新特性(如
java.time.*),編譯時以 -source 1.8 -target 1.8 產出 class 檔。
- 官方發布的 JAR 經過動態字節碼重寫(Animal Sniffer + 多版本 JAR 技術),運行時根據實際 JDK 版本載入對應實現類,故 JDK 7 環境下 JAR 正常運作。
- 直接引入源碼模組繞過此機制,Eclipse 編譯器預設遵循專案 JDK 版本(1.7),編譯含
java.time 的源碼自然失敗。
解決方案
- 升級專案編譯環境至 JDK 8+(推薦)
Eclipse:Project → Properties → Java Compiler → Compiler compliance level 1.8
並安裝 JDK 8 配置 JRE。
- 僅附加源碼不編譯
專案建置路徑 → Libraries → Spring JAR → Source Attachment → 指向源碼 ZIP/目錄,不將源碼加入 Source 標籤。調試時 IDE 會自動對應行號。
- 使用 Spring Boot 親測版本
Spring Boot 2.x 基線已升至 JDK 8,避免版本衝突。
官方技術文檔
How Spring Achieves Compatibility with Java 6, 7 and 8 詳細說明多版本 JAR 打包原理。
最佳實踐建議
- 調試第三方庫源碼時,優先使用 Source Attachment,避免污染專案編譯環境。
- 新專務直接起步 JDK 17/21 LTS,Spring 6 / Spring Boot 3 已要求 JDK 17+。
- 若必須維護舊專案,建議以 Docker 封裝 JDK 7 運行環境,開發環境統一升級。