搭建jdk源码阅读环境

Administrator
发布于 2021-08-16 / 381 阅读
0
0

搭建jdk源码阅读环境

一、关联源码调试(有缺陷)

第一步:新建一个JAVA项目

new一个最简单的java项目,如图,一直next最后finish就行了。这边给项目起的名——JavaSourseLearn,代表jdk源码学习。
image.png

第二步:源码解压

找到Project Structure(ctrl + shift + alt + s),找到SDKs -> Sourcepath,可以看到源代码src.zip的存储位置。

image.png

src.zip解压,删除com目录(这块代码不需要,而且不删除会因为缺少部分文件而报错),解压目录随意。

第三步:修改配置

  • Project Structure - SDKs,点击新增("+"),新增1.8_clone(名字自取),删除sourcepath里面的src.zip源码,将源码链接指向src.zip解压的目录。

image.png

  • Project Structure - Modules,引用前面新增的sdk;或者是修改Project -> Project SDK。

image.png

  • 编写hashmap测试代码,尝试调试

image.png

启动debug,f7发现进不去hashmap的构造方法。因为idea限制了一些包com.sum.、java.、javax.*等等不能step into。修改配置如图。

image.png

如果debug run提示资源不足,可以尝试如图方法。(非必要,这边就没有出现这种情况)
image.png

第四步:编写测试代码,debug调试代码。

此时,如上上上图,step into hashmap的构造函数。我们尝试加点注释。如下图。

image.png

增加单行注释会导致debug错位,当然我们可以增加行尾注释避免错位的问题(但是这不够优雅)。根据上图我们可以得知,执行的代码还是jdk的代码,不是执行我们修改的source目录下的源代码,所以我们在源代码上增加比如System.out.print的代码也是不生效的(除非重新编译jdk)。

二、CentOS7编译open jdk8

1、拉取源代码

注意不要用git先在windows拉取源码再放到linux,会出现大量换行符问题,windows是\r\n,linux是\n。如果是要编译linux的源码,直接在linux安装git拉取代码。因为文件的换行符在git拉取的那一瞬间就决定了。

# 拉取jdk代码
git clone https://github.com/openjdk/jdk
# 进入代码目录
cd jdk
# 切换到 tag标记 jdk-b120, github上8版本的最新的tag
git checkout jdk8-b120

2、安装BootStrap JDK

需要安装BootStrap JDK,也就是前导jdk,用来引导jdk编译的。比如我们要编译jdk8,就要先安装jdk7(比当前要编译的版本早一些的版本,最好是早一个版本号。这边使用的是jdk-7u80-linux-x64.tar.gz——解压出来是jdk1.7.0_80)。

3、linux上安装必要的工具集(我的是CentOS)

yum install -y zip
yum groupinstall -y 'Development Tools'
yum install -y libXtst-devel libXt-devel libXrender-devel
yum install -y cups-devel
yum install -y alsa-lib-devel
yum install -y freetype-devel

4、编译

可以把export以及编译命令写成shell脚本,因为export不写进/etc/profile退出shell将失效。

# jdk是刚拉取的源代码根目录
cd jdk
# 设置configure执行权限
chmod +x configure

# 设置编译参数
export LANG=C
# 使用预编译头文件,不加这个编译会更慢一些
export USE_PRECOMPILED_HEADER=true

#比较本次build出来的映像与先前版本的差异。这对我们来说没有意义,
#必须设置为false,否则sanity检查会报缺少先前版本JDK的映像的错误提示。
#如果已经设置dev或者DEV_ONLY=true,这个不显式设置也行
export SKIP_COMPARE_IMAGES=true

# 要编译的内容
export BUILD_LANGTOOLS=true
export BUILD_HOTSPOT=true
export BUILD_JDK=true
 
#把它设置为false可以避免javaws和浏览器java插件之类的部分的build
export BUILD_DEPLOY=false
 
# 把它设置为false就不会build出安装包。因为安装包里有一些奇怪的依赖
# 但即使不build出它也已经能得到完整的JDK映像,所以还是别build它好了
export BUILD_INSTALL=false

unset JAVA_HOME
unset CLASSPATH
unset JAVA_TOOL_OPTIONS

# configure检查(注意前导jdk7必须提前安装)
bash ./configure --with-target-bits=64 --with-boot-jdk=/usr/local/jdk1.7.0_80 --with-debug-level=slowdebug --enable-debug-symbols ZIP_DEBUGINFO_FILES=0

最后这个提示可以无视,直接编译

image.png

# 检查无误,开始编译
make all CONF=linux-x86_64-normal-server-slowdebug ZIP_DEBUGINFO_FILES=0

编译成功如图所示(如果编译失败会自动退出)

image.png

检测下我们自己是否编译成功了,进入jdk/build/linux-x86_64-normal-server-slowdebug/jdk/bin目录下,执行./java -version

make clean (清除之前的数据,用于修改源码后多次编译)

ide中使用jdk的源码路径

jdk/jdk/src/share/classes/

注:如果在ide中使用src.zip,调试时会找不到部分package源码,如sun.misc.*。

#这个对上前面【一、关联源码调试(有缺陷)】删除com目录的操作
jdk/build/linux-x86_64-normal-server-slowdebug/images/src.zip

注意:这个编译的jdk大约1G左右,而且这个jdk是无法在win上跑的,所以win上使用idea的同学无法配置这个jdk,这种方式编译的jdk只能在mac、ubuntu、centOS等类unix的平台上使用,如果使用mac的同学可以直接编译完然后再idea里配置就可以了。

另外因为环境变量配置export LANG=C,所以如果安装的系统是中文版本的,会让系统无法识别中文,甚至中文乱码。我的centOS原来echo $LANGen_US.UTF-8不是中文版的不会出现这种问题。

所以在编译完后,如果怕出现中文乱码问题,还需要进行设置
运行:vim /etc/locale.conf 查看是不是 LANG=zh_CN.UTF8
如果不是,那么进行修改。如果是,不用修改,直接退出。
接着运行:source /etc/locale.conf 然后系统语言切换到中文。

三、Win10编译open jdk8

1. 编译环境说明

2. 软件安装

通过git下载openjdk8

# git在提交时把CRLF转换成LF,签出时不转换。因为源文件是lf,在cygwin上执行也要lf,不设置pull下来就变成crlf。
git config --global core.autocrlf input
# clone jdk8最后一个标签版本 -b是标签tag --depth 表示克隆深度, 1 表示只克隆最新的版本
git clone -b jdk8-b120 --depth=1 https://github.com/openjdk/jdk.git

cygwin

cygwin安装步骤

首先安装cygwin:这个是模拟Linux环境的软件,主要编译工作在里面。

cygwin官网:http://www.cygwin.com/

注意:cygwin安装目录和cygwin package安装目录最好分开。比如cygwin装在D:/cygwin,cygwin package安装在D:/cygwin/download。

image.png
需要安装的Package:

Binary NameCategoryPackageDescription
ar.exeDevelbinutilsThe GNU assembler, linker and binary utilities
make.exeDevelmakeThe GNU version of the ‘make’ utility built for CYGWIN
m4.exeInterpretersm4GNU implementation of the traditional Unix macro processor
cpio.exeUtilscpioA program to manage archives of files
gawk.exeUtilsawkPattern-directed scanning and processing language
file.exeUtilsfileDetermines file type using ‘magic’ numbers
zip.exeArchivezipPackage and compress (archive) files
unzip.exeArchiveunzipExtract compressed files in a ZIP archive
free.exeSystemprocpsDisplay amount of free and used memory in the system

image.png

不知道是不是哪里弄错了,装了92G的文件,安装的时候注意下磁盘空间是否够。

cygwin配置环境变量

将cygwin安装路径下的bin目录配置到环境变量path中,如我的安装路径为:D:\develop\openjdk\cygwin\bin

image.png

vs2010安装

需要该软件的原因:JDK中最核心的代码(Java虚拟机及JDK中Native方法的实现等)是使用C++语言及少量C语言编写的,官方文档中说他们的内部开发环境是Microsoft Visual Studio C++ (VS2003)中进行编译,及Microsoft Visual Studio C++ (VS2010)测试过。

解压iso文件,双击setup.exe,一直下一步最后finish。安装完桌面如果没有快捷方式:开始 -> 所有程序 -> Microsoft visual studio 2010 ->Microsoft visual studio 2010,找到后创建到桌面快捷方式。(安装路径不要有空格)

第一次打开vs2010,选择VC++,如下图。
image.png

FreeType安装

需要该软件的原因:这是一个免费的字体渲染库,JDK的Swing部分和JConsole这类工具使用到。

将下载的freetype2.7解压。接下来介绍通过vs2010编译64位的freetype-2.7。

编译freetype

vs2010打开freetype,如下图。我的freetype路径:D:\develop\openjdk\freetype-2.7

image.png

打开后,右键项目,选择properties,如图
image.png

编译freetype.lib:

image.png
image.png
image.png
image.png

编译freetype.dll

image.png
image.png

然后跟上一步一样build。编译好的文件,文件在freetype目录下,我的是D:\develop\openjdk\freetype-2.7\objs\vc2010\x64

image.png

在freetype目录下新建lib并将上面编译的两个文件复制进去,如下图。
image.png

编译openjdk之前会校验并用到freetype下的include文件下的ft2build.h和lib文件夹下的dll和lib文件

设置freetype的环境变量

FREETYPE_CFLAGS=D:\develop\openjdk\freetype-2.7\include
FREETYPE_LIBS=D:\develop\openjdk\freetype-2.7\lib

image.png
image.png

编译openjdk

打开Cygwin,切换到解压的openjdk8的文件夹根目录,如
image.png
执行命令:

bash ./configure -with-freetype=/cygdrive/d/develop/openjdk/freetype-2.7 -enable-debug -with-target-bits=64 --with-boot-jdk=/cygdrive/d/develop/jdk/jdk7 --disable-ccache

命令解析:

  • -with-freetype参数是使用指定的freetype
  • --with-debug-level=slowdebug。用来设置编译的级别,可选值为release、fastdebug、slowde-bug,越往后进行的优化措施就越少,带的调试信息就越多。默认值为release。slowdebug 含有最丰富的调试信息,没有这些信息,很多执行可能被优化掉,我们单步执行时,可能看不到一些变量的值。所以最好指定slowdebug 为编译级别。
  • -enable-debug是编译可调试的openjdk,fastdebug级别
  • -with-target-bits=64,是指编译64位的。
  • --with-boot-jdk:指定引导JDK所在目录,以防其他安装的JDK影响
  • --with-jvm-variants=server : 编译JVM的模式,有server, client, kernel, zero and zeroshark 五种 ,默认server模式;
  • --enable-debug-symbols ZIP_DEBUGINFO_FILES=0:生成调试的符号信息,并且不压缩;(用这个提示找不到objcopy,懒得弄了,把这个去掉)

再执行上述操作前如果设置了环境变量JAVA_HOME, CLASSPATH 记得删除,否则会报错。

编译时遇到的问题:

  1. 提示cygwin版本太老((ˉ▽ˉ;)...这个是2021/8/20官网下载的最新版本),这是检测脚本的bug,该脚本在common/autoconf目录下使用文本编辑器打开generated-configure.sh搜索Your cygwin is too old,关注7249行原来是1.7这里我根据自己的cygwin版本改成了3.2.0。

image.png
image.png

  1. 提示找不到freetype-2.7/lib的freetype.dll。因为上一步vs2010编译的时候我们没有修改freetype的名称。我们的文件名称是freetype27MT.dll,修改成freetype.dll(这个上一步的流程已经修改改成freetype了,不会出现这个问题)。

image.png

最终,configure检测完毕:
image.png

最后make clean && make all编译。
编译时可能出现的错误:

  1. 在configure中加入参数 --disable-ccache
    image.png

  2. CreateJars.gmk格式异常
    image.png
    解决办法:用vi打开jdk/make目录下的CreateJars.gmk

cd /cygdrive/d/develop/openjdk/openjdk8/jdk/make
vi CreateJars.gmk

定位到268行,相距不远处有两个$$换行符,将其转换为Windows下的换行符。

在VI下,可输入268gg。

将光标定位到两个$$之前,按i切换到insert模式后,按Ctrl + V, Ctrl + M,即可打出^M。

完成后按esc退出编辑模式,然后按:进入命令模式,输入wq保存并退出。
image.png

  1. 修改源码增加中文编译报错

image.png
image.png

找到jdk/make/Setup.gmk,用文本编辑器打开(我是vs code),搜索一下encoding,默认是ascii,改成utf-8并保存。之后修改代码或者加中文注释就不会出现编码问题啦。

编译完的结果在build\windows-x86_64-normal-server-fastdebug中。
image.png

jdk编译出来的成品在images文件夹下, 如我的D:\develop\openjdk\openjdk8\build\windows-x86_64-normal-server-fastdebug\images\j2sdk-image,这个和我们从官网下载的基本一样。

调试:

idea新建项目jdkLearn,新建SDKs,Classpath指向D:\develop\openjdk\openjdk8\build\windows-x86_64-normal-server-fastdebug\images\j2sdk-image,SourcePath指向D:\workshop\idea-mine\jdk\jdk\src。

修改源码后,要重新编译执行make images,这次是增量编译会快很多。

官网上编译用:make images,的确,make all编译花了我们比较多的时间,而且编译的大部分我们也用不上。后面configure后可以直接make images
verify用images下的java文件:

Verify your newly built JDK:
./build/*/images/jdk/bin/java -version

不想make clean,直接make images增量编译但是报错了。去目录\build\windows-x86_64-normal-server-fastdebug\jdk 下删除objs和demoobjs,将这两个文件夹下的所有文件删除。重新编译正常,我这边重新编译花费4、5分钟。

参考与鸣谢:

https://blog.csdn.net/qq_39575279/article/details/81609395
https://blog.csdn.net/wqlinloveruby/article/details/80409031
https://blog.csdn.net/weixin_34144450/article/details/92575977
https://blog.csdn.net/wangshuaiwsws95/article/details/107375724
https://blog.csdn.net/linpeijieaini/article/details/118891404


评论