如果你是刚要被Java军训的新兵,可有几时对环境搭建而不知所措?又如若你是驰骋Java战场多年的老将,可曾拿起陪伴你许久的82年的JDK回味一番?今天我们就来道一道JDK,重新来认识认识这个既熟悉又陌生的伙伴。

既然要唠唠JDK,首先想到的,肯定是要了解下都是谁来推进Java和JDK发展的。

Java发展的会议与组织

说起Java的起源必定要提起Sun公司,由其发起了专属于Java的JavaOne会议。不过Sun公司被Oracle收购后,JavaOne会议同Oracle先前的Oracle OpenWorld会议并成了Oracle Code One会议,并且会议内容也不再单纯讨论Java的发展。另外还有JCP(Java Community Process)是个开放性的国际技术标准组织,职责是发展和更新Java 技术规范,由其推出了大量Java相关技术规范JSR,具体可点此查看。JCP的运作方式是由个人或者厂商提出JSR规范提案,再有JCP委员会的成员投票表决是否采用。其弊端是JCP委员会还是主要由厂商组成,这些规范可能更偏向于厂商的利益,而非大众的利益。

JDK版本

我们要知道Java应用开发并不是只有常接触的移动端 、服务端的应用开发。Sun公司根据不同业务领域方向分成了四个JDK版本:

  • Java Card,主要是以具有安全防护性的方式来执行小型的Java Applet,广泛运用在SIM卡、提款卡上;
  • Java SE,前称J2SE。Java的标准版,为JavaEE和JavaME提供了基础类库以及能力。也是我们安装部署Java环境最基础的版本;
  • Java EE,前称J2EE。针对企业级应用的加强版。主要涉及的技术:JDBC、EJB(被Spring遮住了光芒)、Servlet、RMI、JNDI、JMS、JPA、JTS等。Java 10版本以后被Oracle公司放弃,捐献给了Eclipse基金会,并后成为Jakarta EE;
  • Java ME,前称J2ME。主要用于移动设备、嵌入式设备上的java应用程序;

Oracle JDK vs Open JDK

至于它俩的区别,下面的列表基本列出:


如果你们公司既想应用新特性,又没有授权的话,那就使用OpenJDK 11吧!毕竟Oracle的产品总监也说了,Oracle JDK是基于OpenJDK源代码构建的,OracleJDK和OpenJDK在Java 11后,功能基本保持一致。可见链接:Oracle JDK Releases for Java 11 and Later

各版本特性及重要事件

JDK 1.0在1996年1月23日发布,Java语言有了第一个正式版本的运行环境;

JDK 1.2,Sun公司正式将Java拆分成J2SE,J2EE和J2ME三大技术体系;

JDK 1.6,终结了J2EE、J2SE、J2ME的命名方式,启用Java SE 6、JavaEE 6、Java ME 6的命名方式。与此同时,Sun公司宣布将对Java技术开源;

JDK 7,Sun公司被Oracle公司收购,发布时间延期;

JDK 8,Oracle启用JEP(JDK Enhancement  Proposal)定义管理新版JDK发布的新特性,完成了JDK 7规划了但没有实现的功能,HotSpot移除掉永久代,吸收了JRockit的Java Mission Control监控工具等功能;8u201/202版本后,如果是用作商业用途,需要收费;

JDK 9,jigsaw模块化、增强jshell、jlink、jhsdb等工具,并支持了91个JEP;此前均以特性驱动发行版本。9开始变成以时间驱动,发布周期为6个月一个大版本,3年一个 LTS版本;

JDK 10,主要是JDK内部重构,只支持了12个JEP;Oracle公司抛弃Java EE,捐献给Eclipse基金会;

JDK 11,推出了ZGC垃圾收集器(只支持64位的Linux机器),支持了17个JEP;第一个官宣的LTS发行版;

JDK 12:推出非Oracle开发的Shen-andoah垃圾收集器,OracleJDK随后剔除了,存在于OpenJDK,支持了8个JEP;

JDK 13:支持5个JEP;

JDK 14:推出Windows和MacOS的ZGC垃圾收集器,支持16个JEP;

各版本具体的New Feature,大家可以直接上Oracle官网追溯。或者查看我推荐的两篇博文:博文1传送门博文2传送门。我这里就不再赘述了,后面会开个专栏,去探索实践Java每个版本特性的实现。

精华!!!解密JDK包

JDK的运用,渗透到从事Java开发工作的各位的每一天,从开发到调试,再到发布和部署,以及上线后的运维都息息相关。相信在座的各位,一定有过疑问,jdk到底是怎么组成的?了解这些可能对我们的开发工作没有太多的作用,但是哪位又能预料明天和bug哪个先到呢,也许这就是你找到问题根因的地方!再不济,学习点知识,总不会有坏处!跟随我的脚步,一起看看JDK到底是怎么构成的吧!

组成架构

我们先来看下官方文档中Java SE版本JDK的组成架构图:

回首Java——再回首JDK-LMLPHP

很直接地可以看出,最下面的Java HotSpot VM,是Java运行最基础的组件;Java SE API即我们日常编程使用的Java类库;JRE是Java应用程序运行的最小环境,其中包括了JVM,Java SE API类库和其他标准或非标准组件;JDK包含了JRE和一些Tool。Java8增加新特性Compact Profiles,是因为Java丰富的类库在小型应用中显得有些累赘,便将JRE分成了三种实现,compact1、compact2和compact3,具体的拆分情况如下,可见数字越大,包含的内容越多。在编译时,使用option: -profile,指定对应的实现方式即可。

回首Java——再回首JDK-LMLPHP

JDK文件组成

以windows环境的Java 8u261版本为例,针对JDK的组成架构进行解读。先来了解下解压或者安装完JDK的文件夹结构吧:

回首Java——再回首JDK-LMLPHP

  • bin目录中存放了开发过程的编译解释工具,如java.exe、javac.exe等,以及开发运维工作中常用的资源消耗统计等不同功能的辅助工具,如jmap.exe、jconsole.exe、jstat.exe等。
  • include目录下可以看到都是以.h结尾的文件,用来支持Java中用到的本地方法以及JVM调试程序接口用到的本地技术。
  • jre目录则是jdk运行的开发环境时使用的runtime,如jdk bin目录下的执行文件都是建立在这个jre文件夹的基础上 !当然也是可以单纯用于Java编写的程序。需要说明的,如果存在期望依赖的jar包(如中间件的驱动程序),可以放置于jre的lib目录下的ext文件夹 。
  • lib目录是存放JDK bin目录下可执行文件依赖的jar包等,如常见的tools.jar;
  • src.zip则是Java类库源码,主要包含rt.jar,以及程序启动器Launcher源码,主要功能是创建ExtClassLoader和AppClassLoader,根据配置创建SercurityManager,设置进程上下文类加载器;

JVM

Oracle官网po出组成架构图最下面便是最基础、最重要的JVM技术,是在真实计算机上模拟虚拟的计算机功能。正是它的存在,才成就了“一次编译,多次运行”;

Java8后提供了两种模式的VM,一种是Client,通常用于客户端应用程序,可以减少应用的启动时间和内存占用,一种是Server,会提升运行时执行速度;在jvm.cfg文件中第一个是默认实现,默认是-server KNOWN,KNOWN可设置成IGNORE,这只是表示相应的option是否启用。

此处列出两个Q&A,这也是我最初接触JVM的疑问。

Q1:JVM作为Java程序最重要的组件,为什么文件夹里没有一个很明显的文件表示用于JVM的呢?

A1:JVM以动态库的形式存在,Windows上置于jre的bin文件夹下的server或者client文件夹里的jvm.dll。Linux上置于jre的lib文件下的/amd**/server或者/amd**/client文件夹下的libjvm.so。

Q2:JVM是怎么被加载并实例化的?

A2:JVM加载是通过java.exe来完成:首先通过launcher下的main函数创建JVM装载环境、配置,然后装载jvm.dll,装载完成后通过JNI本地调用接口找到JNI_CreateJavaVM的函数地址,然后调用函数去实例化JNIEnv对象:JVM,最后便通过JVM实例装载并处理class文件。代码调用顺序如下,童鞋可自行看下源码:main() > JLI_Launch() > CreateExecutionEnvironment() > SetJvmEnvironment() > LoadJavaVM() > JVMInit() > JavaMain() > InitializeJVM() > CreateJavaVM() [调用JNI接口] > LoadMainClass() > GetApplicationClass() ;

哦~~原来是这样啊!是不是对JVM进一步认识了呢?不过这才是皮毛,剩下的等我开个专题慢慢道来!还不赶紧关注我?

 JRE 依赖包

JRE运行所依赖的jar包,包含在/jre/lib和/jre/lib/ext文件夹下,如果有jar包希望作为JVM信任的Jar包第一时间加载,也可以直接将jar包置于/jre/lib/ext文件夹下。介绍下所有依赖的jar包:

rt.jar介绍

Java SE版本涉及的基础核心类库,源码则可以将jdk的src.zip解压后查看。但是并非rt.jar中的所有包都是有源码的。不知道具体原因是什么,有没有了解的童鞋评论下点拨下。

具体API都可以在https://docs.oracle.com/javase/8/docs/api/index.html查看,或者下到电脑自行查看,不同版本的API直接将"/8/"变更成你需要的Java版本即可。

接下来介绍下组成架构图中Java SE规范除去UI Toolkits的模块以及功能。

JDK提供的工具

所有提供的工具按照类别分组情况如下,具体的使用方法可以下载JDK的文档查看。

  • 基本工具 (appletviewer, extcheck, jar, java, javac, javadoc, javah, javap, jdb, jdeps)
  • 安全工具 (keytool, jarsigner, policytool, kinit, klist, ktab)
  • 国际化工具 (native2ascii)
  • RMI工具 (rmic, rmiregistry, rmid, serialver)
  • Java IDL和RMI-IIOP工具 (tnameserv, idlj, orbd, servertool)
  • 部署工具 (javapackager, pack200, unpack200)
  • Java Web Start工具 (javaws)
  • 故障排除,性能分析,监视和管理工具 (jcmd, jconsole, jmc, jvisualvm)
  • Web服务工具 (schemagen, wsgen, wsimport, xjc) 

Java 9及以后

上述的组成架构图,是基于Java 8的解析。在Java9前,由于之前JRE必须要整体部署运行,会造成一定程度不期望的性能影响或者资源消耗。Oracle公司针对这方面的考虑,在JCP组织上做了很多的工作,终于在Java 9上实现了模块化。

Java 9之前是通过不同的package和jar对功能做区分隔离,Java9后,可以通过不同的module进行隔离。

如果打开JDK 9后文件夹,你会发现jre文件夹不存在了,出现了新的文件夹:jmods。文件夹下面的每个文件都是一个组件,每个组件都会有一个module-info.class文件。打开文件你会发现,存在着类似nodejs等语言常用的关键字:用requires引入需要的组件、 用exports暴露的包名;其中java.base是最基础的模块,其他组件不需要显示requires。

module java.sql {
    requires transitive java.logging;
    requires transitive java.transaction.xa;
    requires transitive java.xml;

    exports java.sql;
    exports javax.sql;

    uses java.sql.Driver;
}

笔者也还未曾使用过Java 8以后的版本编写过项目,童鞋们有没有优秀的文章分享分享呢?

总结

通过上述的篇幅,我们可以知道:

1. JVM在JRE(JDK)中是以动态链接库的形式存在的,windows中是jvm.dll,linux中是libjvm.so

2. JDK 8有3种实现的compact JRE,数字越大,功能越丰富

3. 组成架构图中的Java SE API部分,位于/jre/lib和/jre/lib/ext文件夹下jar包中

4. rt.jar包是Java SE最为核心的包

5. 组成架构图中的Tools部分,位于jdk的bin目录下的可执行的二进制文件

6. JDK 9后 Java SE API不再是以jar形式存在,而是.jmod文件,针对不同的功能进行模块化

现在对JDK的组成结构到实际开发运用是否有了进一步理解呢?有疑问的地方,欢迎童鞋们留言讨论! 

08-02 05:44