zoukankan      html  css  js  c++  java
  • 源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

    一、前言

    前一阵子比较好奇,想看到底层(虚拟机、汇编)怎么实现的java 并发那块。

    volatile是在汇编里加了lock前缀,因为volatile可以通过查看JIT编译器的汇编代码来看。

    但是原子类,本来在jvm中就是汇编实现的,反而没法看。如果能实际跟踪一下断点,应该也算实际验证了。

    这边基本参照下面文章来的,补充了很多让初学者头疼的细节,并拓展了一部分,

    包括调试java 原子类在jvm中的实现的一些细节。

    https://marcin-chwedczuk.github.io/debugging-openjdk8-with-netbeans-on-ubuntu

    源码编译OpenJDK8,主要有以下几个步骤:

    • 下载Ubuntu
    • 下载OpenJdk源码
    • 下载Boot  JDK,一般要比当前要编译的版本低
    • 安装必要的依赖
    • configure && make

    上面几步搞完,基本虚拟机就可用了。但离调试,还有一点点距离。

    用NetBeans调试JVM代码,有以下几个步骤:

    • 下载NetBeans
    • 配置OpenJdk工程
    • 配置Java工程
    • Debug OpenJdk(即虚拟机源码)

    二、源码编译OpenJDK8

    1、下载Ubuntu

    我用的16.04,链接地址:https://www.ubuntu.com/download/alternative-downloads

    我是用vmvare装的,配置建议给高一点。

    2、下载OpenJdk源码

    据原文说法,OpenJDK 使用Mercurial进行版本管理。另外一个名叫AdoptOpenJDK project.提供了OpenJDK的镜像,可以让我们用git下载。

    站点的官网如下:https://adoptopenjdk.net/about.html 

    主页上说他们的目标就是:

    Provide a reliable source of OpenJDK binaries for all platforms, for the long term future.

    据我的使用体验来说,之前编译过一次OpenJDK,各种报错,各种改源码才能编译通过。这次确实编译很顺,代码一句没改。

    看起来,代码还是比较可靠的。

    不扯别的了,直接clone搞下来吧,我这边是直接在/home/ckl目录下执行的shell:

    git clone --depth 1 -b master https://github.com/AdoptOpenJDK/openjdk-jdk8u.git

    3、下载Boot JDK

    编译过jdk的同学应该知道,我们得先有只母鸡才能编译openJDK源码。

    这边我用的oracle的jdk 1.7,这边贴个csdn的下载链接,我那天弄的时候官网速度太慢。

    https://download.csdn.net/download/qq_33499492/10288883

    怎么安装就不说了,我解压后放在/usr/local

    记得修改环境变量(/ect/profile):

    export JAVA_HOME=/usr/local/jdk1.7.0_80
    export JRE_HOME=${JAVA_HOME}/jre
    export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
    export PATH=${JAVA_HOME}/bin:$PATH

    然后,source /ect/profile 使之生效。

    4、安装依赖

    sudo apt install 
            libx11-dev 
            libxext-dev 
            libxrender-dev 
            libxtst-dev 
            libxt-dev 
            libcups2-dev 
            libfreetype6-dev 
            libasound2-dev

    这个依赖不够,我这边装的时候,还报了一些依赖缺失,直接安装报错提示里的执行命令下载就完了。

    我这里遇到比较坑的一点是(当然我对ubuntu完全不熟),一开始用的是官方的repository 源,后来换成阿里云的,各种报错。

    吓得我赶紧改回来了,就没问题了。

    这里遇到问题可以咨询我。

    5、配置脚本

    在/home/ckl/openjdk-jdk8u下,新建脚本build.sh:

    build.sh:

    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
    make all ZIP_DEBUGINFO_FILES=0

    给build.sh增加可执行权限并执行:

    chmod +x build.sh
    ./build.sh

    6、编译成功的效果

     切换到对应目录下:

    /home/ckl/openjdk-jdk8u/build/linux-x86_64-normal-server-slowdebug/jdk/bin
    ./java -version

    在该目录下,新建个HelloWorld来运行一下:

    public class HelloWorld {
        public static void main(String[] args) {
            System.out.println("hello world");
        }
    }

    三、Netbeans调试JVM

    1、下载NetBeans 8.2

    下载安装主要参考:

    https://netbeans.org/community/releases/82/install.html

    NetBeans主页上,最新版本出到11.0了,但是在网上看到都是用的NetBeans 8开头版本的,有时间再折腾吧。

    我这里下载的是8.2,链接:

    https://netbeans.org/downloads/8.2/

    因为OpenJDK是c++写的,所以我们必须选择带C/C++支持的,我这里直接选All。

    另外,注意选linux平台,最好选英语,免得出幺蛾子。

    2、下载oracle jdk 1.8

    为啥又要下载jdk? 这个jdk不是编译openJdk源码用的那个,这个是运行NetBeans 8.2需要。

    The Java SE Development Kit (JDK) 8 is required to install NetBeans IDE.

    下完安装后,把环境变量里设的jdk路径改掉吧:

    export JAVA_HOME=/usr/local/jdk1.8.0_211
    export JRE_HOME=${JAVA_HOME}/jre
    export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
    export PATH=${JAVA_HOME}/bin:$PATH
    source /etc/profile

    3、安装net beans

     安装:

    ./netbeans

    安装过程,记得不要全部默认,可以自己定制化:

     

    4、配置Open JDK工程

    安装完成后,在桌面上,会生成一个图标,直接双击启动。

    后面的步骤,可以参考:

    https://marcin-chwedczuk.github.io/debugging-openjdk8-with-netbeans-on-ubuntu

     

     

    然后接下来几步都可以直接next,最后点finish会开始configure。

    5、运行HelloWorld

    配置我们的openjdk工程去运行之前写的HelloWorld程序。

    对着openjdk-jdk8u工程,右键选择properties:

    选择编译出的jdk来运行我们的class:

     

    应该能看到输出Hello World了。

    6、调试Hello World

    System.out.println(...)会调用jdk/src/share/native/java/io/io_util.c的writeBytes

    直接在该函数打个断点,然后debug

    不出意外,应该会停到该断点。

    7、在netbeans中新建java工程,并调试jvm

    我们来调一个有用点的程序,看看原子类在jvm中的实现到底是不是像网上的博客那样运行的。

    先像上面这样,建个java工程,写点代码,然后运行。

    import java.util.concurrent.atomic.AtomicBoolean;
    import java.util.concurrent.atomic.AtomicInteger;
    
    
    /**
     *
     * @author ckl
     */
    public class TestSample {
        private static AtomicInteger stop = new AtomicInteger(12);
        
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            
            Boolean result = stop.compareAndSet(1314, 1413);
            // TODO code application logic here
            if (result){
                System.out.println(" true result ");
            }else {
                System.out.println("false result");
            }
        }
        
    }

     调试jvm:

    对着openjdk-jdk8u工程点右键,properties。

    建立断点,cas调用一般会调用unsafe.cpp的以下代码:

    断点ok了,然后点选中openjdk-jdk8u工程后,点击debug按钮:

     果然,程序马上就停在这了。但是,cas操作可能在很多地方都调用了,所以我们要仔细观察Variables窗口,看看是不是我们发起的那个调用:

    跳过了十多次以后。。。

    。。。

     稍微跟一下:

    直接进到这段汇编了,用了cmpxchg指令来实现cas,还加了lock前缀(mp为1)。lock前缀下次讲。主要是锁总线,或者锁缓存,达到原子操作的目的。

    有问题欢迎留言,如果有问题,也可以加我微信交流。

  • 相关阅读:
    centos下升级python
    微信公众号(二)
    微信公众号的开发(一)
    nginx 新手入门
    Mysql is not allowed to connect mysql server
    docker 新手入门 (阿里镜像仓库的使用)
    docker 新手入门 (web项目的部署)
    jquery easyui combox不能编辑只能选择
    $.messager.confirm 用法
    html下载excel模板
  • 原文地址:https://www.cnblogs.com/grey-wolf/p/10971741.html
Copyright © 2011-2022 走看看