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.javasun.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

曹工力荐:调试 jdk 中 rt.jar 包部分的源码(可自由增加注释,修改代码并debug)

利用原始的javac编译整个Java项目

Mac环境下的Java操作

IDEA调试源码并写注释

shell脚本中针对sudo等密码输入的问题解决方案

shell中让脚体自动输入sudo密码方法

bash shell 获取当前正在执行脚本的绝对路径

Linux Shell 计算脚本执行过程用了多长时间

date命令时间戳和时间之间的转换

原文地址:https://www.cnblogs.com/vitoboy/p/15683218.html