openjdk9u源码分析一:搭建环境(原创)

openjdk9u源码分析一:搭建环境

搭建环境可分两步,
  1. 搭建jdk9u编译环境
  2. 搭建jdk9u调试环境
实验环境
   1. Mac OS X: 10.13.3.
   2. Xcode: 9.2.
   3. boot jdk: 1.8.0_162.
   4. freetype: 2.9.
   5. XQuartz-2.7.11.
   6. GDB-8.0.1.

1.搭建jdk9u编译环境

  • 目标:从官网下载openjdk9u源码,正确编译打包出jdk9u可执行文件,能够编译、运行helloworld程序。
  • 搭建过程:参考https://www.yanshuo.me/p/156958,按照这篇文章能够正确编译出可运行的jdk9u。我的环境和参考链接中的基本上一致,除了使用的boot jdk,我使用的1.8.0_162,而参考文章使用的1.8.0_161。
  • 结果验证:
  • 编译后的结果位于源码根目录/build下:


    openjdk9u源码分析一:搭建环境(原创)_第1张图片
    build-result-tree.jpg

目前阶段只关注hotspot、images和jdk子目录,其中hotspot存放jvm的编译结果,images存放jdk、jrem,doc等产品文件,jdk存放jdk编译结果。

  • 验证build出来的jdk版本:


    build-version.jpg
  • Run一个helloworld类:


    helloworld-verify.jpg
  • 问题总结:

    1. 网上资料以编译jdk7、8为主,总结比较全面的文章请参考https://github.com/ydcun/Java/blob/master/java/src/main/java/com/ydcun/openjdk/jdk8/MAC%E7%BC%96%E8%AF%91OpenJDK8.md,折腾了半天jdk8的编译,把hotspot8u40给捣腾出来了,但在运行hotspot时提示找不到libjvm.dylib:

    unable to load native library:dlopen(/Library/Java/JavaVirtualMachines jdk1.7.0_10.jdk/Contents/Home/jre/lib/libjava.dylib, 1):Symbol not found: \_JVM\_SetProtectionDomain Referenced from: /Library/Java/JavaVirtualMachines/jdk1.7.0\_10.jdk/Contents/Home/jre/lib/libjava.dylib Expected in: /Users/Desktop/hotspot-68577993c7db/build/bsd/ bsd\_amd64\_compiler2/fastdebug/libjvm.dylib

    这个错误应该是没有编译jdk8u40的源码,只编译了hotspot的源码,我用boot jdk7代替了jdk8造成的,但并没有实际去验证。看了jdk9u的文章后,里面提到“因为编译8需要Xcode 4现在Xcode版本已远高于4了”,就放弃了jdk8的编译,但现在看,未必是Xcode的版本影响了8的编译。

    1. 在编译jdk8时,要求安装XQuartz,我安装了XQuartz-2.7.11,但并未能创建这两个链接:
      sudo ln -s /usr/X11/include/X11 /usr/include/X11
      or
      sudo ln -s /usr/local/X11/include/X11 /usr/include/X11
      后面编译成功说明这个问题可以忽略。
    2. 源码推荐从http://hg.openjdk.java.net/jdk-updates下载。首先下载根目录,然后再分别下载各个子目录,下载完后解压到根目录下,如下图所示:
      openjdk9u源码分析一:搭建环境(原创)_第2张图片
      folder-tree.jpg
openjdk9u源码分析一:搭建环境(原创)_第3张图片
src-download.jpg

其中,hotspot是JVM的源码目录,jdk存放jdk源码,强烈建议在编译之前先读common/doc/下的build文件。其他目录的功能说明大家可网上了解即可,对于编译过程,基本没影响,如果要运行jdk自带的测试代码,需要关注test目录。 其他两种下载源码的方式:使用Mercurial的hg,openjdk的源码通过mercurial进行管理。但正如网友@since1986在博文中所述,每次都是下载到一定大小的内容后,程序自动退出;还有网友修改了get_source.sh脚步,使之自动重连下载,修改的脚步比较多,而且不保证能成功,放弃。另外,git上有上传的代码,参见https://github.com/luodaxu/blog-1/blob/master/Java/hotspot-debug-under-osx.md,但并未验证。

  1. 设置环境变量。
  • 设置boot jdk path。方便起见,下载了jdk7,jdk8两个版本,jdk7用于实验,8用于工作,如果想直接编译jdk9,jdk7也不需要额外安装。
        export JAVA\_8\_HOME=$(/usr/libexec/java\_home \-v1.8)  
        export JAVA\_7\_HOME=$(/usr/libexec/java\_home \-v1.7)  
        alias java7='export JAVA\_HOME=$JAVA\_7\_HOME' 
        alias java8='export JAVA\_HOME=$JAVA\_8\_HOME'  
        \# default java8  
        export JAVA_HOME=$JAVA\_8\_HOME
  • 设置编译参数。每个参数上都有说明,大家自行查阅,并可以根据实验机器的配置进行调整。本文仅对build和compile的job数进行了修改,编译一遍通过。
        \# 设定语言选项,必须设置  
        export LANG=C  
        \# Mac平台,C编译器不再是GCC,是clang  
        export CC=clang  
        \# 跳过clang的一些严格的语法检查,不然会将N多的警告作为Error  
        export COMPILER\_WARNINGS\_FATAL=false
        \# 链接时使用的参数  
        export LFLAGS='\-Xlinker \-lstdc++'  
        \# 是否使用clang  
        export USE\_CLANG=true  
        \# 使用64位数据模型  
        export LP64=1
        \# 告诉编译平台是64位,不然会按32位来编译  
        export ARCH\_DATA\_MODEL=64  
        \# 允许自动下载依赖  
        export ALLOW\_DOWNLOADS=true  
        \# 并行编译的线程数,编译时间长  
        export HOTSPOT\_BUILD\_JOBS=8  
        ALT\_BOOTDIR=$JAVA\_HOME  
        export ALT\_PARALLEL\_COMPILE\_JOBS=2  
        \# 是否跳过与先前版本的比较  
        export SKIP\_COMPARE\_IMAGES=true  
        \# 是否使用预编译头文件,加快编译速度  
        export USE\_PRECOMPILED\_HEADER=true  
        \# 是否使用增量编译  
        export INCREMENTAL\_BUILD=true  
        \# 编译内容  
        export BUILD\_LANGTOOLS=true  
        export BUILD\_JAXP=true  
        export BUILD\_JAXWS=true  
        export BUILD\_CORBA=true  
        export BUILD\_HOTSPOT=true  
        export BUILD\_JDK=true  
        \# 编译版本  
        export SKIP\_DEBUG\_BUILD=true  
        export SKIP\_FASTDEBUG\_BUILD=false  
        export DEBUG\_NAME=debug  
        \# 避开javaws和浏览器Java插件之类的部分的build  
        export BUILD\_DEPLOY=false  
        export BUILD\_INSTALL=false  
  • configure时添加--disable-warnings-as-errors。因为在build hotspot时,如果出现warnings,编译过程会认为失败,实际这些warnings不影响编译的正确性;也可以在环境变量中配置:export COMPILER_WARNINGS_FATAL=false,上述配置已包括。
  1. 有些jvm源码需要修改,详情参见上述参考的链接。

  2. jdk9的模块化等一些新特性不会影响编译过程,正如jdk的一位负责人所说,从老版本迁移到jdk9要比之前的升级过程还简单,至少从编译jdk源码的过程来讲,jdk9u并未增加额外的工作量。

  3. mac下软件安装时,可能会遇到verify stuck的情况,参考http://osxdaily.com/2016/07/26/fix-stuck-pkg-verifying-installer-mac-os-x/解决。

    至此,openjdk9u已经编译成功,并得到一个可用于调试的jvm和jdk。接下来,使用已构建的程序包,调试一个helloworld的程序。该过程网上信息比较少,已有的资料要么jdk版本不一致,要么依赖的软件包版本不同,要么操作系统不同,对于之前未debug jvm的dev,可能是个痛苦的过程,但参考下面的内容后,将会使大家的调试过程变得轻松许多。

搭建jdk9u调试环境

  • 目标:利用已生成的jvm,debug一个java helloworld程序,且能够debug到jvm的源码。
  • 搭建过程:针对jdk8的调试环境搭建,请参考http://blog.csdn.net/tjiyu/article/details/53725247。整个过程可概况为使用GDB(全平台通用)或LLDB(windows版本正在开发,其他平台都支持)debug java这个可执行文件(GDB、LLDB是两种C、C++程序调试工具,由于hotspot主要采用C++和C实现,因此要调试hotspot必须要使用C、C++的调试工具,这些工具可以通过命令行单条执行命令,也可以通过脚步批量执行),入参为待执行的java class文件名,本文中为Test。java可执行文件启动一个hotspot实例来执行Test class。下面分步骤说明环境搭建过程。
  1. 安装GDB。 macOsX high sierra下,Xcode9.2默认使用LLDB,因此需要安装GDB。从GDB官网下载了最新的8.1版本,并安装网上的说明进行sign,否则debug时,eclipse的进度条会一直卡在99%不动。参考https://stackoverflow.com/questions/18423124/please-check-gdb-is-codesigned-see-taskgated8-how-to-get-gdb-installed-w对GDB进行签名,需要注意:证书类型需要先选择login方式,然后再拖拽到system类型下,否则创建证书会报错。如下图所示:
    openjdk9u源码分析一:搭建环境(原创)_第4张图片
    gdb-cert-kind.jpg

后来验证的过程说明,GDB相关的问题是调试环境安装过程中最大的一个坑。
* 添加"set startup-with-shell off" >> ~/.gdbinit,.gdbinit是gdb的初始化文件,也可以在执行gdb之前执行set startup-with-shell off。
* 执行csrutil status,查看Debugging Restrictions配置项的值,如果是enabled,需要更改为disabled。参考https://stackoverflow.com/questions/39702871/gdb-kind-of-doesnt-work-on-macos-sierra/40437725#40437725,需要reboot,并在安全模式下执行。
* 回退到8.0.1版本,事实证明8.1.0与OS X 10.13.3兼容性不好。参见https://gist.github.com/gravitylow/fb595186ce6068537a6e9da6d8b5b96d。在因为GDB抛出"During startup program terminated with signal SIGTRAP, Trace/breakpoint trap."问题时,曾尝试使用LLDB进行debug,但LLDB虽然能跑完测试程序,但看不到java程序的输出,最终还是使用GDB进行调试时看到了java的输出。LLDB调试参见https://github.com/luodaxu/blog-1/blob/master/Java/hotspot-debug-under-osx.md,但通过LLDB与GDB的对比,也找到了GDB不能输出的原因,即在gdb捕获segment invalid异常时,继续执行,在hotspot脚步中添加handle SIGSEGV nostop这一行指令。后面在介绍hotspot脚步时还会详细介绍。通过一个C程序验证GDB已成功安装。

  1. 修改Hotspot文件。该脚步位于./jdk9u-1b1226687b89/build/macosx-x86_64-normal-server-slowdebug/hotspot/variant-server/libjvm/下,它是一个可执行的脚步文件,该文件配置了JDK路径、GDB调试器默认的一些参数,关于该文件的内容可参考《HotSpot实战》这本书第一章的内容或https://yq.aliyun.com/articles/93753?spm=a2c4e.11153940.blogcont93737.16.6da64d09stvTm2。需要说明的有三点:
    * build源码后,该脚步中已经添加了已build的jdk路径,大家可查看hotspot文件中的这一行: JDK=/Users/Desktop/jdk9u-1b1226687b89/build/macosx-x86_64-normal-server-slowdebug/jdk
    * 脚步中init_gdb()函数用于配置gdb参数,默认生成的内容中有handle SIGUSR1 nostop noprinthandle SIGUSR2 nostop noprint这两行,handle命令的意思是debug过程中,gdb如何处理系统信号,在后面添加handle SIGSEGV nostop这一行。
  2. 复制libjvm.dylib文件到hotspot脚步相同目录下。最初通过“./jdk9u-1b1226687b89/build/macosx-x86_64-normal-server-slowdebug/hotspot/variant-server/libjvm/hotspot -gdb Test”测试时,总是得到一个ERROR“Error: missing /Users/.../Desktop/jdk9u-1b1226687b89/build/macosx-x86_64-normal-server-slowdebug/hotspot/variant-server/libjvm' JVM at/Users/Desktop/jdk9u-1b1226687b89/build/macosx-x86_64-normal-server-slowdebug/hotspot/variant-server/libjvm/libjvm.dylib'.
    Please install or use the JRE or JDK that contains these missing components.”
    ,该错误耽误了有半天的时间,最初依赖搜索引擎,但网上在mac high sierra下调试hotspot9的资料基本上没有,只是了解到libjvm就是hotspot的动态库,当时真有些山穷水尽的感觉,于是只能中断一些时间,休息时,libjvm.dylib missing的错误一直在头脑中浮现,某个时刻突然想到libjvm.dylib文件是不是不在hotspot相同目录下,于是查找hotspot/variant-server/libjvm/目录,发现该文件在./libjvm/gtest下,copy一份到hotspot/variant-server/libjvm,即与hotspot文件同目录下,测试Test,得到了期待的结果:
    final-verify.png

图中,绿色方框中的为java程序的输出,红色框中即为GDB收到的segment fault的信号,如果不修改hotspot脚步,GDB会执行不下去。

  • 问题总结:
  • 使用当前比较新的软件版本做一些实验时,网上可参考资料很少,如果对一些问题领域不太熟悉,可能会花费较多的时间和精力;
  • 实验遇到瓶颈时,抓住错误日志不放,休息后换个思路再试;
  • 多尝试不同的思路才可能解决问题;
  • 遇到问题请教网上的专家得到响应的情况几乎为零:(。
    本文知识产权归创造者所有,复制转发发行需经作者同意。

加入公众号获取我的更多原创文章:

openjdk9u源码分析一:搭建环境(原创)_第5张图片
公众号二维码1.jpg

加入“Java编程思想读书会”微信群,和大量技术专家们讨论技术:

openjdk9u源码分析一:搭建环境(原创)_第6张图片
Java编程思想读书会群二维码.jpg

你可能感兴趣的:(openjdk9u源码分析一:搭建环境(原创))