深入理解Java虚拟机——第一章——走进Java

时间:2022-12-27 17:35:21

Java技术体系

JDK(Java Development Kit):Java开发组件,是用于支持Java程序开发的最小环境,包括Java程序设计语言、Java虚拟机、Java API类库。

JRE(Java Runtime Environment):支持Java程序运行的标准环境,包括Java虚拟机、Java API类库中的Java SE API子集。

Java技术体系可以分为4个平台:

  • Java Card:支持一些Java小程序运行在小内存设备(如智能卡)上的平台
  • Java ME(Micro Edition):支持Java程序运行在移动终端上的平台,以前称J2ME
  • Java SE(Standard Edition):支持面向桌面级的应用(如Windows下的应用程序),以前称J2SE
  • Java EE(Enterprise Edition):支持使用多层架构的企业应用,以前称J2EE,一般以javax.*作为包名

JIT(Just In Time)编译器。

Java技术的未来:

  • 模块化:避免为了系统的一小块功能而去安装部署庞大的系统
  • 混合语言:越来越多基于Java虚拟机开发的语言,可用于多语言混合编程。例如并行处理用Clojure,展示层用Jruby,中间层用Java,每种语言针对自己擅长的方面解决问题。

函数式编程(如lambada)的一个重要优点是这样的程序天然地适合并行运行:

函数式编程不需要考虑"死锁"(deadlock),因为它不修改变量,所以根本不存在"锁"线程的问题。不必担心一个线程的数据,被另一个线程修改。如

var s1 = Op1();
var s2 = Op2();
var s3 = concat(s1, s2);
由于s1和s2互不干扰,不会修改变量,谁先执行是无所谓的,所以可以放心地增加线程,把它们分配在两个线程上完成。

编译OpenJDK8:

OS:CentOS 7 64bit; 
OpenJDK:openjdk-8u40; 

注意:下面的OpenJDK源码的编译过程没有设置Bootstrap JDK。

书上说虚拟机有的代码是使用Java自身实现的,因此编译这些Java代码需要用到一个可用的JDK,即“Bootstrap JDK”,这个JDK需要JDK6之后的版本。Bootstrap JDK需要在编译前的环境变量设置里指定路径,但是我没有进行设置,也成功编译了源码,因此不知道这个Bootstrap JDK是否是必须需要的,我编译成功可能是因为本地已经装了一个Java,如果没有在编译前的环境变量里设置,会自动把当前系统的环境变量指定的JDK当成Bootstrap JDK。具体Bootstrap JDK是否需要得在一个没有安装过Java的系统里面测试。

1. 获取JDK源码:

首先安装mercurial,因为OpenJDK是用mercurial管理的。

sudo yum install mercurial

然后克隆源码,运行get_source.sh脚本获得所有源代码。(书上给的能下载到打包好的源码网址https://jdk7.java.net/source.html,现在只能下载到二进制源码,而我们需要的是cpp源码,在网址里的Archive里选择source下载,也是跳转到下面给出的hg网址,应该是选择不给提供打包的源码了)

注意:不能直接从网址里面找gz压缩包下载,然后解压运行get_source.sh脚本,如果没下载mercurial会出现错误ERROR: Could not locate Mercurial command,因为里面还要通过mercurial下载其它源代码,

下载了mercurial再运行也会出现错误ERROR: Need initial repository to use this script,必须得用mercurial的hg命令来克隆项目再运行。应该跟git一样,没有初始化用户信息是操作不了项目仓库里的某个文件,克隆下来整个项目应该会自动包含项目管理者的用户信息,因此可以操作。

 在下载源代码可能会有abort错误,原因是因为外网的问题,自行解决。

hg clone http://hg.openjdk.java.net/jdk8u/jdk8u-dev/
cd jdk8u-dev
sh ./get_source.sh

2. 设置环境变量:

接下去设置环境变量,新建一个sh文件,例如env.sh,填入以下内容,然后sh env.sh执行

# 语言选项
export LANG=C
# 允许自动下载依赖
export ALLOW_DOWNLOADS=true
# 并行编译的线程数,编译时间长,为了不影响其他工作,选择为1
export HOTSPOT_BUILD_JOBS=1
# 是否跳过与先前版本的比较
export SKIP_COMPARE_IMAGES=true
# 是否使用预编译头文件,加快编译速度
export USE_PRECOMPILED_HEADER=true
# 是否使用增量编译
export INCREMENTAL_BUILD=true
# 编译内容
export BUILD_LANGTOOLS=true
export BUILD_JAXP=true
export BUILD_JAXWS=true
export BUILD_CORBA=true
export BUILD_HOTSPOT=true
export BUILD_JDK=true
# 编译版本
export SKIP_DEBUG_BUILD=true
export SKIP_FASTDEBUG_BUILD=false
export DEBUG_NAME=debug
# 避开javaws和浏览器Java插件之类的部分的build
export BUILD_DEPLOY=false
export BUILD_INSTALL=false
unset JAVA_HOME

3. 构建编译环境:

运行OpenJDK源码目录下的configure文件

bash ./configure

如果缺少某个环境,运行configure会提示,按提示的下载即可。

一般需要下载的如下

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

configure运行成功的结果如下

  深入理解Java虚拟机——第一章——走进Java

4. 编译:

 在OpenJDK源码目录下运行make all

make all

编译成功之后显示如下

深入理解Java虚拟机——第一章——走进Java

5. 测试:

当前目录下的bulid文件里有个linux-x86_64-normal-server-release文件夹,就是编译结果。里面有许多文件,其中/images/j2sdk-image有和直接安装OpenJDK后类似Java目录结构,这就是整个JDK的完整编译结果。具体查看过程如下

cd ./build/linux-x86_64-normal-server-release/images/j2sdk-image/bin
./java -version
# 得到
openjdk version "1.8.0-internal"
OpenJDK Runtime Environment (build 1.8.0-internal-xx_2019_07_09_13_56-b00)
OpenJDK 64-Bit Server VM (build 25.71-b00, mixed mode)

 

 

之后这个整个j2sdk-image文件夹就可以被拷贝到任何地方,并配置环境变量使用。

配置变量可以在用户主目录下创建.bash_profile里文件,内容如下(其中OpenJDK_1.8.0就是上面的j2sdk-image的拷贝)

 

export JAVA_HOME=/usr/用户名/java/OpenJDK_1.8.0
export CLASSPATH=./:$JAVA_HOME/lib
export PATH=$JAVA_HOME/bin:$PATH

 

 

 

之后source .bash_profile使环境变量生效,用java -version查看结果。