日志

回首Java——再回首JDK

 来源    2020-08-01    1  

如果你是刚要被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

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

  Oracle JDK Open JDK
起源时间 JDK1.0,1996年1月发行 OpenJDK 6(基于Java SE 7),2007年发行
代码协议

新的OTN协议,2019年1月之后发布的Oracle JDK 8更新将无法用于商业

GPLv2+CE
发行周期

JDK6及之前大约每两年一版本,6至7五年,7至8、8至9三年;JDK10及以后均6个月一个大版本;每3年一个LTS版本;

OpenJDK 9及之前大约三年一个版本;OpenJDK 10及以后均6个月一个大版本;

支持时间

从JDK10起,每6个月一个大版本;从JDK11起,每3年一个LTS长期维护的版本;

从JDK10起,每6个月一个大版本;不发行LTS版本,只维护半年,也就是下个版本发布便不再维护。但是有其他顶级公司继续维护,如Red Hat OpenJDK,Liberica OpenJDK

商标 java商标拥有者 不可使用java
性能 响应能力、JVM性能更强 ——
功能

Flight Recorder,Java Mission Control和Application Class-Data Sharing

Font Renderer,但OpenJDK 11后也包含Oracle JDK的功能,还有Z Garbage Collector


如果你们公司既想应用新特性,又没有授权的话,那就使用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 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,指定对应的实现方式即可。

JDK文件组成

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

  • 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包:

jar包 作用
access-bridge.jar Microsoft Windows操作系统的Java Access Bridge使基于Windows的辅助技术可以与Java Accessibility API进行交互;
charsets.jar 扩展的字符集。rt.jar中sun.nio.cs包下为基础的字符集;
cldrdata.jar 数据标准库,用于数据的国际化和本地化。可见:cldr官网
deploy.jar 用于部署应用的执行安装程序;
dnsns.jar 处理DNS服务,暴露lookupAllHostAddr(),getHostByAddr()方法,用于InetAddress;
jaccess.jar Java Accessibility Utilities实用程序类的一部分,可帮助辅助技术提供对实现Java Accessibility API的GUI工具包的访问;
javaws.jar JNLP协议,支持Java Web Start应用,可以直接通过浏览器执行Java应用程序;
jce.jar 扩展的加密包;
jfr.jar Java飞行记录器,是JMC的一个重要组成部分,用于记录JVM和运行的Java程序的诊断数据、分析数据。对性能影响小于1%;
jfxrt.jar JavaFX的运行时核心jar包,相当于rt.jar
jfxswt.jar 为JavaFX和Swing提供兼容性操作
jsse.jar 用于验证SSL连接的jar
localedata.jar 国际化的数据
management-agent.jar 只有MANIFEST.MF一个文件,用于VisualVM或者JConsole等工具的代理jar包;可查看实际应用介绍
nashorn.jar Java嵌入式的JS引擎,可以实现js与Java的相互调用,还可以使用jrunscript命令运行js;
plugin.jar 用于各种使用场景的插件jar包
resources.jar 用于各种使用场景用到的静态资源,如.properites,.png,.css,.txt等文件

rt.jar

Java的runtime运行时核心代码包

sunec.jar,sunjce_provider.jar,

sunmscapi.jar,sunpkcs11.jar

加密相关的jar包

zipfs.jar

支持对zip压缩包文件操作

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的模块以及功能。

模块 API规范 功能
lang and util

java.lang.*

java.util.*

提供几乎所有Java应用程序的基本功能
Math

java.lang.Math

java.lang.StrictMath

java.math

浮点数计算,数学公式计算
Management

java.lang.management

java.util.logging.LoggingMXBean

javax.management

com.sun.management

com.sun.tools.attach

com.sun.tools.jconsole

提供JVM、JConsole、JMX、日志等监控管理功能
Versioning

java.lang.Class

java.lang.ClassLoader

java.lang.Package

java.lang.System

提供Class、Package管理功能
Ref Objects java.lang.ref 引用对象提供与GC有限交互功能
Reflection java.lang.reflect 反射提供从JVM中查看加载类、修改对象的功能
Collections

基于java.util.Collection的实现

基于java.util.Map的实现

提供了功能强大、设计优秀的集合操作功能
Concurrency Utilities java.utl.concurrent 提供了强大且易扩展的高并发解决方法
JAR

java.util.jar

java.net.JarURLConnection

提供了Jar文件的处理功能
Logging java.util.logging 提供对日志记录的处理和交互
Preferences API java.util.prefs 提供对用户和应用的首选项处理功能
Instrumentation

java.lang.instrument

用于工具来检测Java编程语言应用程序
Regular Expressions

java.util.regex

正则表达式
ZIP

java.util.zip

用于读取和写入标准ZIP和GZIP文件格式
Input/Output

java.io

java.nio

com.sun.nio

提供针对文件和设备I/O处理的丰富功能
Serialization java.io 提供Java对象的序列化和反序列化功能
Networking

java.net

javax.net

com.sun.net

jdk.net等

提供用于网络处理的功能,包括寻址、连接、安全等
Security

java.security

javax.crypto

javax.rmi.ssl

javax.xml.crypto

javax.smartcardio

com.sun.security

org.ietf.jgss等

用于与安全相关的功能的API,如访问控制,数字签名,身份验证和授权,加密等
Internationalization

java.util.spi

java.util.Locale

java.text.DecimalFormatSymbols等

支持开发国际化应用程序的API,可以在不进行工程更改的情况下适应各种语言和地区。
Beans

java.beans

java.beans.beancontext

主要提高了交互性和可维护性,JavaBeans的长期持久性可以读写bean作为其属性值的文本表示形式
JMX  javax.management  Management Extension管理扩展,用于管理和监控资源使用
 XML JAXP

javax.xml

org.w3c.dom

org.xml.sax

 用于处理XML文档和数据
JNI   用于编写Java本机方法并将Java虚拟机嵌入本机应用程序的标准编程接口,可以实现Java与其他语言的交互。推荐一篇介绍如何使用JNI的文章
Extension Mechanism   支持扩展,jar包置于/jdk/jre/lib/ext,二进制文件置于/jdk/jre/bin,JVM会作为可信任文件加载,不做安全检查。已弃用,未来版本删除此功能
Override Mechanism   除JCP外定义的Java API,可以覆盖成新版本作为认可标准版本。未来版本删除功能
IDL

org.omg.CORBA

org.omg.CosNaming

org.omg.PortableServer

org.omg.PortableInterceptor

org.omg.DynamicAny

使分布式、支持Web的Java应用可以基于IIOP协议透明地调用远程服务
JDBC

java.sql

javax.sql

通用数据访问接口,需要驱动进行连接。如常用的mysql-connector-java.jar
JNDI

javax.naming

提供命名和目录功能,以通用方式访问各种服务。如Spring定义的jndi-lookup可以用于Wildfly部署的应用程序来建立数据库连接
RMI

java.rmi

提供调用远程JVM中的Java对象的方法,使用对象序列化来封装和解析
RMI-IIOP

org.omg.CORBA

org.omg.CosNaming

org.omg.PortableServer

javax.rmi

通过Internet Inter-ORB协议技术进行Java远程方法调用RMI编程模型可通过RMI API进行CORBA服务器和应用程序的编程。
Scripting

javax.script

脚本引擎接口,可以实现动态脚本与java的交互,Java SE套件中含有nashorn引擎,可见nashorn.jar

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的组成结构到实际开发运用是否有了进一步理解呢?有疑问的地方,欢迎童鞋们留言讨论! 

参考文章:

1. https://blog.csdn.net/topdeveloperr/article/details/89789132#jdk%E5%8C%85%E6%80%BB%E8%A7%88

2. https://segmentfault.com/a/1190000022711960

相关文章
再回首,Java温故知新(十一):Java反射
日志最近继续回顾Java基础,进行到了Java反射这一部分,个人感觉这部分应该算是Java的高级特性了,在日常开发中使用的并不多,应用人员主要是工具构建人员,所以这次学习中以了解为主,Java反射主要应用 ...
1
再回首,Java温故知新(十):数组
日志数组是程序中用来存储同一类型值的集合,基本所有编程语言中都有这种类型存在.声明数组时需要指出数组类型和数组变量名,初始化后数组的长度不可变,使用过程中通过下标来访问数组中的元素,示例代码如下: int ...
1
再回首,Java温故知新(九):Java基础之流程控制语句
日志流程控制语句分为条件语句.循环语句和中断语句. 中断语句包括break和continue,两者的区别在于break会跳出整个循环,而continue则是跳出此次循环,之后还会继续下一次循环. 条件语句 ...
1
再回首,Java温故知新(七):Java基础之运算符
日志常规算数运算符 包括+.-.*./.%分别对应着加.减.乘.除.取余,算数运算符所处理的两个数字必须为同种类型,如果是不同类型且无法进行自动类型转换的话必须进行强制类型转换,不过强制类型转换可能会丢失 ...
1
再回首,Java温故知新(二):Java基本数据类型
日志Java作为一种强类型语言,意味着每一个变量都会有特定的类型,Java共有8种基本类型,其中有4种整型(byte.short.int.long).两种浮点型(float.double).1种字符型(c ...
1
JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题
日志JAVA基础再回首(二十五)--Lock锁的使用.死锁问题.多线程生产者和消费者.线程池.匿名内部类使用多线程.定时器.面试题 版权声明:转载必须注明本文转自程序猿杜鹏程的博客:http://blog ...
1
MySQL数据库再回首
日志前言: 数据库是程序员的数据源泉,加上近期 要开发DB可视化.性能分析的功能 重新回顾一下MySQL知识,以下是笔记: MySQL架构   MySQL基础理论 1.什么是关系型数据库? 关系型数据库, ...
再回首数据结构—红黑树(一)
日志红黑树与AVL树一样同为二分搜索树,红黑树又称为是保持"黑平衡"的二叉树,红黑树最大高度为:2logn,红黑树由这么几个独特的特征: 1.每个节点或黑或红 2.根节点为黑色 3.每 ...
再回首数据结构—AVL树(二)
日志前面主要介绍了AVL的基本概念与结构,下面开始详细介绍AVL的实现细节: AVL树实现的关键点 AVL树与二叉搜索树结构类似,但又有些细微的区别,从上面AVL树的介绍我们知道它需要维护其左右节点平衡, ...
1
再回首数据结构—AVL树(一)
日志前面所讲的二叉搜索树有个比较严重致命的问题就是极端情况下当数据以排序好的顺序创建搜索树此时二叉搜索树将退化为链表结构因此性能也大幅度下降,因此为了解决此问题我们下面要介绍的与二叉搜索树非常类似的结构就 ...
再回首数据结构—二叉搜索树
日志二叉搜索树(Binary Search Tree)为非线性结构,树与链表一样为动态数据结构也可称二叉搜索树为多个链表所组成实现的,由于二叉搜索树性能比较高所以属于比较常用的数据结构:二叉搜索树每个节点 ...
1
再回首数据结构—链表
日志链表与数组一样同为线性数据结构,不少编程语言也自带了链表的实现,链表可以存放不同数据类型的数据: 与数组不同,数组占用内存结构必须为连续,而链表则不需要内存空间为连续的:链表由多个节点连接而成,每个节 ...
再回首数据结构—数组(Golang实现)
日志数组为线性数据结构,通常编程语言都有自带了数组数据类型结构,数组存放的是有个相同数据类型的数据集: 为什么称数组为线性数据结构:因为数组在内存中是连续存储的数据结构,数组中每个元素最多只有左右两个方向 ...
1
java – 通过标准JDK 11使用graalvm
问答我有项目使用Nashorn Javascript引擎.我正在尝试迁移到java11,并从Nashorn迁移到Graal.我已经阅读了here,我可以通过从JDK 11开始的标准JDK安装使用graal ...
1
java – 制作Oracle JDK docker镜像
问答我正在尝试为oracle JDK创建docker镜像,但我能找到的唯一图像是打开的JDK.我们的应用程序使用oracle JDK,因此必须构建oracle JDK docker镜像.我的问题是,是否有 ...
1
java – ‘android-24’需要JDK 1.8或更高版本编译
问答我使用Android Studio和最近得到的错误: Error:Execution failed for task ':app:compileDebugJavaWithJavac'. compile ...
1
java – 配置Oracle JDK以使用IBM JCE / JSSE提供程序来实现FIPS合规性
问答我想将Oracle JDK配置为使用IBM的符合FIPS标准的JCE / JSSE安全提供程序.我需要哪些JAR文件以及它们应该安装在何处? java.security文件中的提供者列表应该是什么样的 ...
1
Java 64位JDK问题
问答如果我使用64位JDK编译一些java文件然后从它们中创建一个JAR文件,那么生成的JAR是否正确地使用32位JRE,或者我是否必须使用32位JDK? 谢谢::生成的JAR将正确地使用32位JRE.你 ...
1
java – 记住从JDK 8 lambda返回的最后一个值
问答我为指数函数汇总了Taylor系列扩展的快速Java实现,因为它简单而有趣: package math.series; import java.util.stream.IntStream; /** * ...
1
java – Oracle的JDK zip文件系统中的错误,你如何编写SSCCE来重现它?
问答最新的1.7和1.8版本的JDK(7u72,8u25)中存在此错误.必需:jackson-databind 2.5.0.在Linux x86_64上测试(准确地说是Ubuntu 14.10). 码: ...
1