jvm原理1:cenos编译openjdk8

简介: 近期在研究jvm原理,看了不少书,总感觉停留在理论上,不能系统的学习以及深入理解。以及正所谓“纸上得来终觉浅,绝知此事要躬行”,要想深入的了解jvm原理,最起码要手动编译一个jdk以及虚拟机玩玩。

近期在研究jvm原理,看了不少书,总感觉停留在理论上,不能系统的学习以及深入理解。以及正所谓“纸上得来终觉浅,绝知此事要躬行”,要想深入的了解jvm原理,最起码要手动编译一个jdk以及虚拟机玩玩。本文总结一下自己在cenos6中编译openjdk8的一些粗浅经验,供大家参考学习。

1.操作系统说明

本文使用的cenos系统版本为cenos6.4 64位。可以使用如下的命令进行查看。

[root@localhost test]# uname -a
Linux localhost 2.6.32-358.el6.x86_64 #1 SMP Fri Feb 22 00:31:26 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

2.编译

 2-1:获取源码

在本次的openjdk编译中,我们使用的版本为openjdk8.因此我们需要获取到openjdk8的源码。

openjdk8源码的获取方式有两种方式

1.使用hg工具进行源码的下载。

2.直接在官网进行下载源码包(下载地址)。

2-1-1 hg下载openjdk源码。

这种方式获取源码,比较耗时,下载的耗时时间,完全取决与我们的网速。在这里还是简单说明一下:

  首先,我们需要下载Mercurial。详细步骤如下:

 cd /var/local/    
 wget http://mercurial.selenic.com/release/mercurial-3.0.tar.gz    
 tar xvzf mercurial-3.0.tar.gz    
 mv mercurial-3.0 mercurial    
 cd mercurial    
 make all    
 make install  
上述的命令执行完毕之后,如果没有错误,则输入hg -v命令之后,控制台显示的信息如下:
分布式软件配置管理工具 - 水银
基本命令:
 add           add the specified files on the next commit
 annotate, blame
               show changeset information by line for each file
 clone         make a copy of an existing repository
 commit, ci    commit the specified files or all outstanding changes
 diff          diff repository (or selected files)
 export        dump the header and diffs for one or more changesets
 forget        forget the specified files on the next commit
 init          create a new repository in the given directory
 log, history  show revision history of entire repository or files
 merge         merge another revision into working directory
 pull          pull changes from the specified source
 push          push changes to the specified destination
 remove, rm    remove the specified files on the next commit
 serve         start stand-alone webserver
 status, st    show changed files in the working directory
 summary, sum  summarize working directory state

Mercurial安装完毕之后,我们就开始下载openjdk8的源码,命令如下:
hg clone http://hg.openjdk.java.net/jdk8u/jdk8u jdk8u
cd  jdk8u
bash get_source.sh
经过一段耐心时间的等待,源码就会下载完毕。如果网速不给力的小朋友,可以直接通过我提供的下载地址下载即可。

3、openjdk8源码安装

3.1 安装jdk必备软件包
安装jdk必备软件包如下所示:
yum makecache
yum -y groupinstall 'base'
yum groupinstall "Development Tools"  
yum install libXtst-devel libXt-devel libXrender-devel  
yum install cups-devel  
yum install freetype-devel  
yum install alsa-lib-devel  
大家可以一个个的下载安装即可。

3.2 环境准备

上述的一个个软件包安装完毕之后,我们来开始配置环境。首先我们看一下openjdk-jdk8u-jdk8u中的README-builds.htm文件,这个文件中详细说明了构建openjdk8的步骤以及方法,由于是英文版的,所以在这里我们暂时不一个个的说明了,用到的命令我们再来详细的说明。在构建环境之前,还是简单看一下这个文件,如下:
Some Headlines:
  • The build is now a "configure && make" style build
  • Any GNU make 3.81 or newer should work
  • The build should scale, i.e. more processors should cause the build to be done in less wall-clock time
  • Nested or recursive make invocations have been significantly reduced, as has the total fork/exec or spawning of sub processes during the build
  • Windows MKS usage is no longer supported
  • Windows Visual Studio vsvars*.bat and vcvars*.bat files are run automatically
  • Ant is no longer used when building the OpenJDK
  • Use of ALT_* environment variables for configuring the build is no longer supported
上面的一段话,大体意思就是openjdk8源码的构建可以直接使用 config && make方式。换言之,openjdk8之前的额源码构建需要使用Ant和ALT_ *。需要使用到的make版本为3.81以及以后的版本(包含)。

3.3 make版本检查

在控制台输入make -v命令,输出信息如下:
[root@localhost openjdk-jdk8u-jdk8u]# make -v
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for x86_64-redhat-linux-gnu

3.4 引导启动jdk设置

注意:在编译openjdk8的时候,我们需要安装一个引导启动的jdk,并且这个jdk必须是7版本。这一点需要注意,引导启动jdk的版本要比编译的jdk版本小1。比如我们在编译openjdk7,那么我们需要安装的引导启动jdk版本为6;我们在编译openjdk6,那么我们需要安装的引导启动jdk版本为5。
在这里我使用的引导启动jdk版本为
jdk1.7.0_80,目录为 /opt/jdk1.7.0_80。

4、开始编译openjdk8

上述的环境准备完毕之后,就开始我们的openjdk8编译了。首先我们进入/opt/openjdk-jdk8u-jdk8u目录,输入的命令如下:
cd openjdk  
bash ./configure --with-target-bits=64 --with-boot-jdk=/opt/jdk1.7.0_80 --with-debug-level=slowdebug --enable-debug-symbols ZIP_DEBUGINFO_FILES=0  
make all ZIP_DEBUGINFO_FILES=0

参数说明:

 --with-boot-jdk:指定引导JDK所在目录,以防其他安装的JDK影响(本机上以前安装了JDK8,并配置了JAVA_HOME指向JDK8);

      --with-target-bits:指定编译64位系统的JDK;

        

为可以进行源码调试,再指定下面三个参数:

      --with-debug-level=slowdebug:指定可以生成最多的调试信息;

      --enable-debug-symbols ZIP_DEBUGINFO_FILES=0:生成调试的符号信息,并且不压缩;这个调试的时候非常有用。

命令最终执行完毕之后,即可完成编译,因为我实在虚拟机中进行openjdk8的编译,所以大概花费了2个小时。

5.测试编译的openjdk

编译的文件位于build/linux-x86_64-normal-server-slowdebug中,我们继续进入子目录,完整目录如下:

/opt/openjdk-jdk8u-jdk8u/build/linux-x86_64-normal-server-slowdebug/jdk/bin

输入java -version命令,效果如下所示:

[root@localhost bin]# java -version
java version "1.8.0_162-ea"
Java(TM) SE Runtime Environment (build 1.8.0_162-ea-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.162-b01, mixed mode)

ok,当看到上面的命令成功执行之后,便说明我们的openjdk8手工编译成功了。






    

相关文章
|
11月前
|
Oracle Java 关系型数据库
JVM深入原理(一+二):JVM概述和JVM功能
JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行。
292 0
|
11月前
|
Arthas 存储 Java
JVM深入原理(三+四):JVM组成和JVM字节码文件
目录3. JVM组成3.1. 组成-运行时数据区3.2. 组成-类加载器3.3. 组成-执行引擎3.4. 组成-本地接口4. JVM字节码文件4.1. 字节码文件-组成4.1.1. 组成-基础信息4.1.1.1. 基础信息-魔数4.1.1.2. 基础信息-主副版本号4.1.2. 组成-常量池4.1.3. 组成-方法4.1.3.1. 方法-工作流程4.1.4. 组成-字段4.1.5. 组成-属性4.2. 字节码文件-查看工具4.2.1. javap4.2.2. jclasslib4.2.3. 阿里Arthas
206 0
|
11月前
|
存储 安全 Java
JVM深入原理(五):JVM组成和JVM字节码文件
类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析。
203 0
|
11月前
|
Arthas Java 测试技术
JVM深入原理(六)(一):JVM类加载器
目录6. JVM类加载器6.1. 类加载器-概述6.2. 类加载器-执行流程6.3. 类加载器-分类(JDK8)6.3.1. JVM底层实现的类加载器6.3.1.1. 启动类加载器6.3.2. Java代码实现类的加载器6.3.2.1. 扩展类加载器6.3.2.2. 应用程序类加载器6.4. 类加载器-Arthas查看类加载器
222 0
|
11月前
|
Java 关系型数据库 MySQL
JVM深入原理(六)(二):双亲委派机制
自定义类加载器打破双亲委派机制的方法:复写ClassLoader中的loadClass方法常见问题:要加载的类名如果是以java.开头,则会抛出安全性异常加载自定义的类都会有一个共同的父类Object,需要在代码中交由父类加载器去加载自定义类加载器不手动指定parent会默认指定应用类加载两个自定义类加载器加载同一个类会被认为是两个对象,只有相同的类加载器+想通的类限定名才会被认为是一个对象。
373 0
|
11月前
|
存储 安全 Java
JVM深入原理(七)(一):运行时数据区
栈的介绍:Java虚拟机栈采用栈的数据结构来管理方法调用中的基本数据,先进后出,每一个方法的调用使用一个栈帧来保存栈的组成:栈:一个线程运行所需要的内存空间,一个栈由多个栈帧组成栈帧:一个方法运行所需要的内存空间活动栈帧:一个线程中只能有一个活动栈帧栈的生命周期:栈随着线程的创建而创建,而回收会在线程销毁时进行栈的执行流程:栈帧压入栈内执行方法执行完毕释放内存若方法间存在调用,那么会压入被调用方法入栈,执行完后释放内存,再执行当前方法,直到执行完毕,释放所有内存。
240 0
|
11月前
|
存储 缓存 安全
JVM深入原理(七)(二):运行时数据区
堆的作用:存放对象的内存空间,它是空间最大的一块内存区域.栈上的局部变量表中,可以存放堆上对象的引用。静态变量也可以存放堆对象的引用,通过静态变量就可以实现对象在线程之间共享。堆的特点:线程共享:堆中的对象都需要考虑线程安全的问题垃圾回收:堆有垃圾回收机制,不再引用的对象就会被回收方法区的概述:方法区是存放基础信息的位置,线程共享,主要包括:类的元信息:保存了所有类的基本信息运行时常量池:保存了字节码文件中的常量池内容静态常量池:字节码文件通过编号查表的方式找到常量。
177 0
|
11月前
|
缓存 算法 Java
JVM深入原理(八)(一):垃圾回收
弱引用-作用:JVM中使用WeakReference对象来实现软引用,一般在ThreadLocal中,当进行垃圾回收时,被弱引用对象引用的对象就直接被回收.软引用-作用:JVM中使用SoftReference对象来实现软引用,一般在缓存中使用,当程序内存不足时,被引用的对象就会被回收.强引用-作用:可达性算法描述的根对象引用普通对象的引用,指的就是强引用,只要有这层关系存在,被引用的对象就会不被垃圾回收。引用计数法-缺点:如果两个对象循环引用,而又没有其他的对象来引用它们,这样就造成垃圾堆积。
273 0
|
11月前
|
算法 Java 对象存储
JVM深入原理(八)(二):垃圾回收
Java垃圾回收过程会通过单独的GC线程来完成,但是不管使用哪一种GC算法,都会有部分阶段需要停止所有的用户线程。这个过程被称之为StopTheWorld简称STW,如果STW时间过长则会影响用户的使用。一般来说,堆内存越大,最大STW就越长,想减少最大STW,就会减少吞吐量,不同的GC算法适用于不同的场景。分代回收算法将整个堆中的区域划分为新生代和老年代。--超过新生代大小的大对象会直接晋升到老年代。
281 0
|
Rust 安全 Java
JVM原理与实现——Synchronized关键字
在多线程Java程序中,`Synchronized`关键字用于确保线程安全。本文深入探讨其工作原理,通过分析字节码`monitorenter`和`monitorexit`,解释JVM如何实现同步机制。文章展示了`Synchronized`方法的编译结果,并详细解析了轻量锁和重度锁的实现过程,包括Mark Word的状态变化及CAS操作的应用。最后简要介绍了`ObjectMonitor::enter()`函数在获取重度锁时的作用。
312 0
JVM原理与实现——Synchronized关键字