源码编译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 -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:
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、编译成功的效果
切换到对应目录下:
- /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..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前缀下次讲。主要是锁总线,或者锁缓存,达到原子操作的目的。
有问题欢迎留言,如果有问题,也可以加我微信交流。
源码编译OpenJdk 8,Netbeans调试Java原子类在JVM中的实现(Ubuntu 16.04)的更多相关文章
- 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 ...
- JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类
JDK1.8源码阅读笔记(2) AtomicInteger AtomicLong AtomicBoolean原子类 Unsafe Java中无法直接操作一块内存区域,不能像C++中那样可以自己申请内存 ...
- Android stdio Apktool源码编译
Android Apktool源码编译 标签(空格分隔): Android Apktool 源码编译 需求 习惯NetBeans调试smali需要用Apktool反编译apk,需要用-d的参数才能生成 ...
- mpusher 源码编译 for windows X64
mpusher 源码编译 for windows X64 对于java我是小白,通过一步步的摸索,将经验总结下来,给更多码友提供入门的帮助.一个人的摸索是很困难的,本教程感谢 [MPush开源消息推送 ...
- 保姆级教程——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版)的亲身经历,包括遇到的问题及解决办法,也有一些 ...
- Ubuntu 16.04下为Android编译OpenCV 3.2.0 Manager
http://johnhany.net/2016/07/build-opencv-manager-for-android-on-ubuntu/ 最近想在Android上尝试一下SIFT和SURF匹配算 ...
- JVM源码分析-JVM源码编译与调试
要分析JVM的源码,结合资料直接阅读是一种方式,但是遇到一些想不通的场景,必须要结合调试,查看执行路径以及参数具体的值,才能搞得明白.所以我们先来把JVM的源码进行编译,并能够使用GDB进行调试. 编 ...
- JVM之---Java源码编译机制
Sun JDK中采用javac将Java源码编译为class文件,这个过程包含三个步骤: 1.分析和输入到符号表(Parse and Enter) Parse过程所做的工作有词法和语法分 ...
- OPENJDK 源码编译
一.整体编译 我的环境: Ubuntu 16.04 LTS apache-ant-1.8.0-bin.zip 环境变量: export LANG=C export ALT_BOOTDIR=/home/ ...
随机推荐
- 8086 IO读写操作
如图所示,通过8086来读写io口,实现流水灯以及开关.本电路是基于8086最小模式下的三总线结构添加的,三总线结构原理较为复杂本篇就不对其原理进行介绍了,大家可以自行查阅相关引脚的功能从而实现. 本 ...
- SVG波浪动画
今天来试试用svg+css3制作波浪动画 下图是我制作出的效果 还不错吧 在制作波浪前,首先我们要画波浪啊,至于画波浪,如果你想直接通过计算贝塞尔曲线绘制出波浪... 好吧,那我也不拦着你 我就直接用 ...
- 了解一下zookeeper,搭建单机版和集群版的环境玩玩,需要手稿的,留下邮箱
第一章:Zookeeper介绍 Zookeeper,动物管理员,是用来管理hadoop(大象).Hive(蜜蜂).Pig(小猪)的管理员. Apache Hbase和Apache Solr的分布式集群 ...
- Socket 连接问题之大量 TIME_WAIT
简评:最近项目就出现了大量短连接导致建立新连接超时问题,最后是通过维护长连接解决的. 代理或者服务器设备都有端口限制,如果使用 TCP 连接,连接数量达到端口限制,在这种情况下,将不能创建新的连接. ...
- 初学者的linux - 基本知识篇
1.Linux系统结构 Linux是一套免费使用和自由传播的类Unix操作系统,它是一种倒树结构. “/”就是系统的顶级目录,称作根目录,“/bin,/root,/home,/etc.."这 ...
- Kotlin学习快速入门(2)——条件 数组 循环 方法
条件 if条件判断 常用的判断和Java一样,这里提一下不同的用法 1.if可以作为三元运算符 val max = if (a > b) a else b 2.使用in判断是否在某个区间 val ...
- bootstrap-treeview后台Json数据的封装及前台的显示
1.bootStrap-treeview是我们常用的树形结构,页面风格也比较清新,但是后台数据的封装比较麻烦,经过研究终于解决,和大家分享一下. 2.前端代码如下 <script> var ...
- 备战金九银十,Java研发面试题(Spring、MySQL、JVM、Mybatis、Redis、Tomcat)[带答案],刷起来!
八月在即,马上就是"金九银十",又是跳槽招聘季.咱们这行公认涨薪不如跳槽加的快.但不建议频繁跳槽,还是要学会融合团队,抓住每个机会提升技能. 苏先生在这里给大家整理了一套各大互联网 ...
- Oracle 数据库登录、用户解锁、改密码、创建用户授权操作
一.数据库登录1.常用账户: 管理员: sys主要练习操作用户: scott2.测试环境是否配置成功: 1.命令窗口 win+R -> cmd(以管理员身份运行) - > sqlplus ...
- tomcat 启动是 jdbc警告
the web application [ROOT] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregist ...