• 走进JVM之一 自己编译openjdk源码


    想要深入了解JVM,就必须了解其实现机制。了解JVM实现的最好方法便是自己动手编译JDK。好了,让我们开始吧!

    1.  准备工作

    • 获取OpenJDK源码

    本次编译选择的是OpenJDK7u,官方源码包:https://jdk7.java.net/source.html

    • 系统需求

    为了提高效率,尽量选择Linux MacOS作为编译平台。本次使用Ubuntu12.04进行编译。仔细阅读源码包中README-builds.html文档,就可以构建编译环境了。

       

    2.  配置编译环境

    • 编译依赖

    OpenJDK包括虚拟机Hotsport | JDK API | JAXWS | JAXP等。需要各种编译依赖,包括C++C的编译环境,编译JavaJDK(称为Bootstrap JDK),还有用于执行java代码的Ant脚本等等。这些依赖在Linux中都可以通过命令一次安装完成。

    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,但是由于openjdk在后面的编译中出现了bug,所以还是建议大家安装Oracle jdk。注意,bootstrap JDK版本必须在6以上。

    • 环境变量

    OpenJDK在编译时会读取许多环境变量,所以必须对Linux的环境变量进行配置。使用VIM编辑/etc/profile vim /etc/profile

    具体在profile中添加的环境变量如下

    export LANG=C
    
    #BootStrap-JDK的安装路径,替换为自己bootstrap-JDK的路径
    
    export ALT_BOOTDIR=/usr/lib/jvm/java-6-openjdk-i386
    
    #同上,我之前使用的是openjdk编译的,后面运行hotspot时出现问题替换为oracleJDK,读者可以直接替换为OracleJDK
    
    export ALT_JDK_IMPORT_PATH=/usr/lib/jvm/java-6-openjdk-i386
    
    #要编译的内容,读者可以根据需要自行选择
    
    export BUILD_LANGTOOLS=true
    
    #export BUILD_JAXWS=false
    
    #export BUILD_JAXP=false
    
    #export BUILD_CORBA=false
    
    export BUILD_HOTSPOT=true
    
    export BUILD_JDK=true
    
    export SKIP_COMPARE_IMAGES=true
    
    BUILD_DEPLOY=false
    
    BUILD_INSTALL=false
    
    #编译结果存放的路径,建议存放在openjdk源码中build文件夹
    
    export ALT_OUTPUTDIR=/usr/dev/jvm/openjdk/build
    
    export ALLOW_DOWNLOADS=true
    
    #这两个环境变量需要去掉,不然会出问题
    
    unset JAVA_HOME
    
    unset CLASSPATH

    添加完成后,进入openjdk源码路径,通过make sanity命令来检查设置是否正确,如果正确,会返回Sanity check passed

       

    3.  开始编译OpenJDK

    • 使用make命令

    openjdk目录下,输入make命令,正常情况下大概需要30分钟左右,具体速度根据机器性能决定。编译正常结束后,会出现日志清单展示内容,如图

    • 查看编译结果

    进入build/j2sdk-image目录下,查看整个JDK的编译结果,运行java –version

    4.  运行HotSpot

    • 编辑env.sh

    虚拟机的输出结果存放在build/hotspot/outputdir/linux_i486_compiler2路径下,如图

    使用VIM编辑product目录下的env.sh

    我们发现里面已经有了JAVA_HOME CLASSPATH HOTSPOT_BUILD_USER等环境变量,我们还需要添加一个LD_LIBRARY_PATH,否则在运行时还会出现问题。

    LD_LIBRARY_PATH=.:${JAVA_HOME}/jre/lib/i386/native_threads:${JAVA_HOME}/jre/lib/i386:
    
    export LD_LIBRARY_PATH
    • 执行命令启动JVM

    使用如下命令,启动虚拟机,输出版本号

    . ./env.sh
    
    ./gamma –vesion

    成功结果如图

    至此成功编译运行OpenJDK7,下面讲讲过程中遇到的问题。

       

    5.  编译运行过程中可能会遇到的问题

    • OpenJDK6.0bug

    使用OpenJDK6.0作为bootstrap JDK的话,在编译及运行过程中可能会出现类似于这样的错误,运行./gamma时也可能出现,这类错误都属于OpenJDK-6中的bug

    relocation error: /usr/lib/jvm/java-6-openjdk-i386/jre/lib/i386/libjava.so: symbol JVM_FindClassFromCaller, version SUNWprivate_1.1 not defined in file libjvm.so with link time reference

    网上提供的一种解决方案是通过find –name 'CurrencyData.properties' 找到CurrencyData文件,把文件中的时间全部修改为10年以内。然而我尝试了这种方法并不能解决问题,于是尝试把Bootstrap JDKopenjdk-6更换为OracleJDK6,终于解决问题。

    • 未取消掉JAVA_HOME变量

    如果没有在环境变量中添加unset JAVA_HOMEmake Sanity时会出现以下错误

    ERROR: Your JAVA_HOME environment variable is set. This will most likely cause the build to fail. Please unset it and start your build again.
    
    Exiting because of the above error(s).
    
    make: *** [post-sanity] Error 1

    /etc/profile中添加unset JAVA_HOME以解决问题

    还有许多在编译过程中遇到的问题,在前文中已经进行弥补和完善,相信大家按照这些步骤进行编译,会省去不少麻烦。

       

    6.  总结

    通过自己动手编译OpenJDK-7的源码,我们可以深入了解JVM的编译环境以及运行过程。通过解决编译过程中遇到的问题,为后续对JVM的深入探索打下了良好的基础。在此基础上,我们还可以通过NetBeansHotspot进行运行和调试,进一步了解JVM源码的结构与细节。

  • 相关阅读:
    leetcode 7.删除有序数组中的重复项
    python 插入排序
    C# 异常处理
    C# 正则表达式
    C# 特性(Attribute)
    C# 预处理器指令
    C# 命名空间(Namespace)
    C# 文件的输入与输出
    C# 反射(Reflection)
    Python入门示例系列37 常用函数
  • 原文地址:https://www.cnblogs.com/ACFLOOD/p/5528035.html
Copyright © 2020-2023  润新知