源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

时间:2022-09-10 20:55:17

一、前言

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

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

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

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

包括调试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  -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..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:

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

build.sh:

bash ./configure --with-target-bits= --with-boot-jdk=/usr/local/jdk1..0_80/ --with-debug-level=slowdebug --enable-debug-symbols ZIP_DEBUGINFO_FILES=
make all ZIP_DEBUGINFO_FILES=

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

chmod +x build.sh
./build.sh

6、编译成功的效果

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

切换到对应目录下:

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

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

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

三、Netbeans调试JVM

1、下载NetBeans 8.2

下载安装主要参考:

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

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

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

因为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..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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

安装:

./netbeans

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

4、配置Open JDK工程

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

后面的步骤,可以参考:

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

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

5、运行HelloWorld

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

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

应该能看到输出Hello World了。

6、调试Hello World

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

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

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

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

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

先像上面这样,建个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。

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

跳过了十多次以后。。。

。。。

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

稍微跟一下:

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)

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

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

源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)的更多相关文章

  1. ubuntu 16.04上源码编译和安装cgal并编写CMakeLists.txt | compile and install cgal on ubuntu 16.04

    本文首发于个人博客https://kezunlin.me/post/39ab7ed9/,欢迎阅读最新内容! compile and install cgal on ubuntu 16.04 Guide ...

  2. JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类

    JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类 Unsafe Java中无法直接操作一块内存区域,不能像C++中那样可以自己申请内存 ...

  3. Android stdio Apktool源码编译

    Android Apktool源码编译 标签(空格分隔): Android Apktool 源码编译 需求 习惯NetBeans调试smali需要用Apktool反编译apk,需要用-d的参数才能生成 ...

  4. mpusher 源码编译 for windows X64

    mpusher 源码编译 for windows X64 对于java我是小白,通过一步步的摸索,将经验总结下来,给更多码友提供入门的帮助.一个人的摸索是很困难的,本教程感谢 [MPush开源消息推送 ...

  5. 保姆级教程——Ubuntu16.04 Server下深度学习环境搭建:安装CUDA8.0,cuDNN6.0,Bazel0.5.4,源码编译安装TensorFlow1.4.0(GPU版)

    写在前面 本文叙述了在Ubuntu16.04 Server下安装CUDA8.0,cuDNN6.0以及源码编译安装TensorFlow1.4.0(GPU版)的亲身经历,包括遇到的问题及解决办法,也有一些 ...

  6. Ubuntu 16.04下为Android编译OpenCV 3.2.0 Manager

    http://johnhany.net/2016/07/build-opencv-manager-for-android-on-ubuntu/ 最近想在Android上尝试一下SIFT和SURF匹配算 ...

  7. JVM源码分析-JVM源码编译与调试

    要分析JVM的源码,结合资料直接阅读是一种方式,但是遇到一些想不通的场景,必须要结合调试,查看执行路径以及参数具体的值,才能搞得明白.所以我们先来把JVM的源码进行编译,并能够使用GDB进行调试. 编 ...

  8. JVM之---Java源码编译机制

    Sun JDK中采用javac将Java源码编译为class文件,这个过程包含三个步骤:     1.分析和输入到符号表(Parse and Enter)    Parse过程所做的工作有词法和语法分 ...

  9. OPENJDK 源码编译

    一.整体编译 我的环境: Ubuntu 16.04 LTS apache-ant-1.8.0-bin.zip 环境变量: export LANG=C export ALT_BOOTDIR=/home/ ...

随机推荐

  1. MySql经典语句

    1.三个函数: LENGTH  SUBSTR   LOCATE )) order by WebSiteShopUrl desc 2.序号 两种方法 第一种方法: ) ) as it 第二种方法: ; ...

  2. python引入导入自定义模块和外部文件

    参考:http://blog.csdn.net/devil_2009/article/details/15816237 项目中想使用以前的代码,或者什么样的需求致使你需要导入外部的包 如果是web 下 ...

  3. 动手写一个快速集成网易新闻,腾讯视频,头条首页的ScrollPageView,显示滚动视图

    最终效果 更新示例.gif 示例效果.gif 示例效果1.gif 示例效果2.gif 示例效果3.gif 示例效果4.gif 示例效果5.gif 示例效果6.gif 一.构思部分: 打算分为三个部分, ...

  4. luogu2597-[ZJOI2012]灾难 && DAG支配树

    Description P2597 [ZJOI2012]灾难 - 洛谷 | 计算机科学教育新生态 Solution 根据题意建图, 新建一个 \(S\) 点, 连向每个没有入边的点. 定义每个点 \( ...

  5. Lua中的表达式

    [算术操作符] Lua支持常规的算术操作符有:”+”(加法),”-“(减法),”*”(乘法),”/”(除法),”^”(指数),”%”(取模),一元的”-“(负号).所有的这些操作符都用于实数.例如:x ...

  6. 【转载】vi/vim使用进阶: 指随意动,移动如飞 (二)

    本节所用命令的帮助入口: :help usr_03.txt :help motion.txt :help usr_29.txt :help scroll.txt :help folding 上一篇文章 ...

  7. Selenium Web 自动化

    1 Selenium Web 自动化 - Selenium(Java)环境搭建 2 Selenium Web 自动化 - 如何找到元素 3 Selenium Web 自动化 - Selenium常用A ...

  8. 如何查看linux服务器的版本和配置信息

    linux下看配置,可没有windows那么直观.你只能一个一个查看. 一:cpu[root@srv /]# more /proc/cpuinfo | grep "modelname&quo ...

  9. windows及linux下安装django simple captcha 遇到的各种问题及解决的方法

    转载自http://www.cnblogs.com/descusr/p/3225874.html 全部程序写完之后,验证码图片不显示,点击图片地址会提演示样例如以下错误,而且在linux下的纠正办法 ...

  10. 机器学习-支持向量机SVM

    简介: 支持向量机(SVM)是一种二分类的监督学习模型,他的基本模型是定义在特征空间上的间隔最大的线性模型.他与感知机的区别是,感知机只要找到可以将数据正确划分的超平面即可,而SVM需要找到间隔最大的 ...