Mac OS 給jdk8原始碼加註釋或程式碼
前言
網上有很多關於除錯檢視jdk原始碼的教程, 但問題在於添加註釋時, 再次進入debug後, 出現行號對應不上的情況.
當然這種情況也有解決辦法, 即自己編譯jdk原始碼, 然後在idea裡直接引入自己編譯的原始碼, 對原始碼修改或添加註釋後, 再增量編譯一下即可.
但問題就在於這個自己編譯jdk原始碼, 這邊編譯出現各種問題, 大部分都有解決方案, 但對於升級了Mac系統後, 很可能無法很好地成功編譯, 同時, 會造成大量的時間浪費
所以, 這裡參考網上的解決方案, 只編譯需要閱讀的部分原始碼
效果
引入原始碼
找到jdk目錄
- 使用命令
echo $JAVA_HOME
檢視jdk路徑
MacBook:~ user$ echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home
- 使用命令
/usr/libexec/java_home
檢視jdk路徑
MacBook:~ user$ /usr/libexec/java_home
/Library/Java/JavaVirtualMachines/jdk-13.0.2.jdk/Contents/Home
解壓原始碼包
idea引入原始碼
專案引用原始碼
正常閱讀原始碼
這時可以正常閱讀原始碼, 但只能在不改變原始碼行的情況下, 在行末添加註釋
ps: 這是不可接受的
編譯原始碼
建立原始碼專案
建立一個純java專案, 將jdk
目錄下的src
複製過來:
ps:
src/sun
原來是沒有的, 參考網上方案的加上的
主要是openjdk8的兩個類:sun.awt.UNIXToolkit.java
和sun.font.FontConfigManager.java
可以直接到 openjdk 專案下, 指定版本將原始碼複製過來即可
編譯原始碼
使用javac
命令, 編譯src
原始碼
javac -J-Xms1024m -J-Xmx1024m -sourcepath source_code -cp /path/rt.jar:/path/tools.jar -d classes -g @filelist.txt
source_code
: 原始碼的絕對路徑, 如:/Volumes/myplace/jdk8src/src
/path/rt.jar
: 即rt.jar
的絕對路徑: 如:/Volumes/myplace/jdk8src/scripts/rt.jar
- 這個
rt.jar
是本人為了方便, 直接從$JAVA_HOME/jre/lib/rt.jar
複製而來, 放至scripts
路徑下
- 這個
/path/tools.jar
: 即tools.jar
的絕對路徑: 如:/Volumes/myplace/jdk8src/scripts/tools.jar
- 這個
tools.jar
是本人為了方便, 直接從$JAVA_HOME/lib/tools.jar
複製而來, 放至scripts
路徑下
- 這個
classes
: 編譯後的class檔案的存放路徑, 如:/Volumes/myplace/jdk8src/classes
filelist.txt
: 原始碼的java檔案的絕對路徑集合- 通過命令:
find /Volumes/myplace/jdk8src/src -name "*.java" > filelist.txt
得到
- 通過命令:
生成jar包
進入classes
目錄, 執行如下命令生成jar包
jar cf0 rt_debug.jar *
複製到指定目錄
將rt_debug.jar
包儲存到$JAVA_HOME/jre/lib/endorsed
, 即: /Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/lib/endorsed
ps: 如果
endorsed
不存在, 直接建立即可
指令碼自動化
既然流程很清楚, 那就建立指令碼來自動執行, 方便使用
在原始碼專案上新增指令碼
- 指令碼檔案如下, 可參考自己的環境進行修改:
#!/bin/bash
# 注意, mac下, 使用 /bin/bash 執行這個指令碼, 可以編譯成功
# 但使用 /bin/zsh 執行這個指令碼, 編譯失敗, 不知道為什麼....
# 設定開始時間
starttime=`date +%s`
echo "===========編譯開始=============="
echo "--設定基本引數--"
echo ""
# 獲取當前指令碼的路徑
shell_dir=$(cd "$(dirname "$0")";pwd)
echo "shell_dir is : $shell_dir"
echo ""
# 切換到指令碼目錄下
echo "change to $shell_dir"
cd $shell_dir
echo ""
# 獲取當前指令碼路徑
cur_dir=`pwd`
echo "----cur_dir----"
echo "cur_dir is : $cur_dir"
echo ""
# 設定檔案列表 及 檔案的路徑
filelist=$cur_dir"/filelist.txt"
echo "----filelist----"
echo "filelist is : $filelist"
echo ""
# 設定需要的jar包路徑
extlib=$cur_dir"/rt.jar:"$cur_dir"/tools.jar"
echo "----extlib----"
echo "extlib is : $extlib"
echo ""
# 切換到jdk src 原始碼目錄
cd ..
src_project=`pwd`
src_dir=$src_project/src
echo "----src_dir----"
echo "src dir is : $src_dir"
echo ""
# 設定class檔案輸出路徑
src_class=$src_project"/classes"
echo "----src_class----"
echo "src_class is : $src_class"
echo ""
# 將project的src目錄下的所有java檔案的全量名稱存入到project/scripts/filelist.txt檔案中
rm -rf $filelist
find $src_dir -name "*.java" > $filelist
echo ""
# $src_class是存放編譯的class檔案的目錄
rm -rf $src_class
mkdir $src_class
echo "after recreate classes"
echo ""
echo "===========開始編譯=============="
echo "編譯中..."
# 批量編譯java檔案
# 編碼:-encoding utf-8
# 依賴庫以冒號:隔開
#javac -J-Xms1024m -J-Xmx1024m -sourcepath /Volumes/myplace/jdk8src/src -cp /Volumes/myplace/jdk8src/scripts/rt.jar:/Volumes/myplace/jdk8src/scripts/tools.jar -d /Volumes/myplace/jdk8src/classes -g @/Volumes/myplace/jdk8src/scripts/filelist.txt
echo "javac -J-Xms1024m -J-Xmx1024m -sourcepath source_code -cp /path/rt.jar:/path/tools.jar -d classes -g @filelist.txt"
javac -J-Xms1024m -J-Xmx1024m -sourcepath $src_dir -cp $extlib -d $src_class -g @$filelist >> log.txt 2>&1
echo "編譯中..."
echo "===========編譯結束=============="
echo ""
# 進入classes目錄
cd $src_class
cur=`pwd`
echo "change to classpath dir, current dir is : $cur"
echo ""
# 將class檔案打包成jar包
echo "run command : jar cf0 rt_debug.jar *"
echo "package classes to rt_debug.jar"
jar cf0 rt_debug.jar *
echo ""
# 指定新jar包的存放路徑
rt_debug_endorsed_dir=/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/jre/lib/endorsed
echo "target dir is : $rt_debug_endorsed_dir"
echo ""
#如果資料夾不存在,建立資料夾
if [ ! -d $rt_debug_endorsed_dir ]; then
# echo "passwd" | sudo -S shutdown -P now
echo "vito" | sudo -S mkdir $rt_debug_endorsed_dir -P now
echo "create target dir"
echo ""
fi
# 複製jar包到指定路徑
echo "copy rt_debug.jar to target dir: $rt_debug_endorsed_dir"
echo "vito" | sudo -S mv rt_debug.jar $rt_debug_endorsed_dir
echo ""
echo "=====操作結束===="
echo ""
endtime=`date +%s`
echo "本次執行時間: "$((endtime-starttime))"s"
新增使用者配置
- 進入使用者目錄:
cd ~
- 編譯使用者配置:
vim .bash_profile
(Mac 各版本可能不同, 按各自版本修改即可) - 新增配置:
alias compilejdk8="/bin/bash /Volumes/myplace/jdk8src/scripts/compiler.sh"
- 使用配置生效:
source .bash_profile
測試指令碼
- 開啟終端
- 輸入命令:
compilejdk8
, 可以得到如下結果:
- 指令碼執行成功! 可以愉快的玩耍了~~~~~~
參考來源
jdk原始碼寫過註釋後debug提示source code does not match the bytecode
JDK原始碼寫過註釋後DEBUG提示SOURCE CODE DOES NOT MATCH THE BYTECODE