深入理解 JVM 最佳路徑莫過於親自編譯運行 OpenJDK。本文記錄在 Ubuntu 12.04 上編譯 OpenJDK 7u 全過程:依賴安裝、環境變量配置、編譯執行、結果驗證、HotSpot 啟動、常見坑點解決,為 JVM 源碼探索鋪路。
官方 OpenJDK 7u 源碼包:https://jdk7.java.net/source.html。下載解壓至工作目錄 (如 /usr/dev/jvm/openjdk)。
sudo apt-get update
sudo apt-get install build-essential gawk m4 libasound2-dev libcups-dev libxrender-dev \
xorg-dev xutils-dev x11proto-print-dev binutils libmotif3 libmotif-dev ant \
openjdk-6-jdk # 或 Oracle JDK 6+,見下文關鍵說明
關鍵警告:務必使用 Oracle JDK 6/7 作為 Bootstrap JDK。OpenJDK 6 自身存在 Bug (符號 JVM_FindClassFromCaller 缺失) 會導致後續 HotSpot 運行失敗。本文踩坑後驗證:換用 Oracle JDK 徹底解決。
/etc/profile)export LANG=C # Bootstrap JDK 路徑 (必須指向 Oracle JDK) export ALT_BOOTDIR=/usr/lib/jvm/java-6-oracle export ALT_JDK_IMPORT_PATH=/usr/lib/jvm/java-6-oracle # 編譯目標選擇 export BUILD_LANGTOOLS=true export BUILD_HOTSPOT=true export BUILD_JDK=true # export BUILD_JAXWS=false # 可選關閉 # export BUILD_JAXP=false # export BUILD_CORBA=false export SKIP_COMPARE_IMAGES=true export BUILD_DEPLOY=false export BUILD_INSTALL=false # 輸出目錄 (建議在源碼內 build 目錄) export ALT_OUTPUTDIR=/usr/dev/jvm/openjdk/build export ALLOW_DOWNLOADS=true # 必須取消這兩個,否則 sanity check 失敗 unset JAVA_HOME unset CLASSPATH
cd /usr/dev/jvm/openjdk make sanity
輸出 Sanity check passed. 表示環境就緒。
make
預計耗時:30-60 分鐘 (視機器性能)。編譯過程會輸出詳細日志,正常結束顯示構建摘要。
cd build/j2sdk-image bin/java -version
期望輸出:
openjdk version "1.7.0-internal" OpenJDK Runtime Environment (build 1.7.0-internal-xxx) OpenJDK Server VM (build xx.xx-bxx, mixed mode)
路徑:build/hotspot/outputdir/linux_i486_compiler2/product/ (架構相關)。
env.sh)# 文件中已有 JAVA_HOME, CLASSPATH, HOTSPOT_BUILD_USER 等
# 必須添加庫路徑,否則啟動報錯
LD_LIBRARY_PATH=.:${JAVA_HOME}/jre/lib/i386/native_threads:${JAVA_HOME}/jre/lib/i386:
export LD_LIBRARY_PATH
. ./env.sh ./gamma -version
成功輸出 HotSpot 版本信息,標誌著完整編譯運行鏈路打通。
| 問題現象 | 根因 | 解決方案 |
|---|---|---|
relocation error: symbol JVM_FindClassFromCaller not defined | Bootstrap JDK 用了 OpenJDK 6,其 libjava.so 依賴符號在 HotSpot 中缺失 | 換用 Oracle JDK 6/7 作為 ALT_BOOTDIR |
ERROR: Your JAVA_HOME environment variable is set (sanity 階段) | 環境變量 JAVA_HOME 干擾構建系統判斷 | unset JAVA_HOME 在 /etc/profile 中 |
CLASSPATH 干擾 | 同理 | unset CLASSPATH |
| 編譯中斷:缺少庫/頭文件 | 構建依賴包未裝全 | 補裝 libxrender-dev、libcups-dev 等,參考 README-builds.html |
HotSpot 啟動:error while loading shared libraries | LD_LIBRARY_PATH 未正確設置 | 在 env.sh 添加 ${JAVA_HOME}/jre/lib/arch 路徑 |
| 64位系統編譯 32位目標失敗 | 缺少 32位庫 | 安裝 ia32-libs (Ubuntu 12.04) 或多架構支持包 |
hotspot/src)gamma 進程或直接啟動主類通過親手編譯運行 OpenJDK 7,我們:
建議下一步:閱讀《深入理解 Java 虛擬機》配合源碼調試,專題攻克感興趣的 JVM 子系統。