首页 > 编程语言 >Java基础知识(一)

Java基础知识(一)

时间:2024-11-18 17:45:09浏览次数:3  
标签:Java JDK OpenJDK 基础知识 编译 JVM Oracle

文章目录

基础概念

1. Java语言的特点

  1. 简单易学(语法简单,上手容易);
  2. 面向对象(封装,继承,多态);
  3. 平台无关性( Java 虚拟机实现平台无关性);
  4. 支持多线程( C++ 语言没有内置的多线程机制,因此必须调用操作系统的多线程功能来进行多线程程序设计,而 Java 语言却提供了多线程支持);
  5. 可靠性(具备异常处理和自动内存管理机制);
  6. 安全性(Java 语言本身的设计就提供了多重安全防护机制如访问权限修饰符、限制程序直接访问操作系统资源);
  7. 高效性(通过 Just In Time 编译器等技术的优化,Java 语言的运行效率还是非常不错的);
  8. 支持网络编程并且很方便;
  9. 编译与解释并存;

2. Java SE vs Java EE

  • Java SE(Java Platform,Standard Edition): Java 平台标准版,Java 编程语言的基础,它包含了支持 Java 应用程序开发和运行的核心类库以及虚拟机等核心组件。Java SE 可以用于构建桌面应用程序或简单的服务器应用程序。
  • Java EE(Java Platform, Enterprise Edition ):Java 平台企业版,建立在 Java SE 的基础上,包含了支持企业级应用程序开发和部署的标准和规范(比如 Servlet、JSP、EJB、JDBC、JPA、JTA、JavaMail、JMS)。 Java EE 可以用于构建分布式、可移植、健壮、可伸缩和安全的服务端 Java 应用程序,例如 Web 应用程序。

简单来说,Java SE 是 Java 的基础版本,Java EE 是 Java 的高级版本。Java SE 更适合开发桌面应用程序或简单的服务器应用程序,Java EE 更适合开发复杂的企业级应用程序或 Web 应用程序。

除了 Java SE 和 Java EE,还有一个 Java ME(Java Platform,Micro Edition)。Java ME 是 Java 的微型版本,主要用于开发嵌入式消费电子设备的应用程序,例如手机、PDA、机顶盒、冰箱、空调等。Java ME 无需重点关注,知道有这个东西就好了,现在已经用不上了。

当前用于嵌入式应用程序的主要语言有C,C+++,JavaScript,PHP等.

3. JVM vs JDK vs JRE的区别

a. JVM

Java 虚拟机(Java Virtual Machine, JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。字节码和不同系统的 JVM 实现是 Java 语言“一次编译,随处可以运行”的关键所在。

如下图所示,不同编程语言(Java、Groovy、Kotlin、JRuby、Clojure …)通过各自的编译器编译成 .class 文件,并最终通过 JVM 在不同平台(Windows、Mac、Linux)上运行。

20241118170730

JVM 并不是只有一种!只要满足 JVM 规范,每个公司、组织或者个人都可以开发自己的专属 JVM。 也就是说我们平时接触到的 HotSpot VM 仅仅是是 JVM 规范的一种实现而已。

除了我们平时最常用的 HotSpot VM 外,还有 J9 VM、Zing VM、JRockit VM 等 JVM 。维基百科上就有常见 JVM 的对比:Comparison of Java virtual machines ,感兴趣的可以去看看。并且,你可以在 Java SE Specifications 上找到各个版本的 JDK 对应的 JVM 规范。

b. JDK

JDK(Java Development Kit)是一个功能齐全的 Java 开发工具包,供开发者使用,用于创建和编译 Java 程序。它包含了 JRE(Java Runtime Environment),以及编译器 javac 和其他工具,如 javadoc(文档生成器)、jdb(调试器)、jconsole(监控工具)、javap(反编译工具)等。

如果需要编写、编译 Java 程序或使用 Java API 文档,就需要安装 JDK。某些需要 Java 特性的应用程序(如 JSP 转换为 Servlet 或使用反射)也可能需要 JDK 来编译和运行 Java 代码。因此,即使不进行 Java 开发工作,有时也可能需要安装 JDK。如果需要编写、编译 Java 程序或使用 Java API 文档,就需要安装 JDK。某些需要 Java 特性的应用程序(如 JSP 转换为 Servlet 或使用反射)也可能需要 JDK 来编译和运行 Java 代码。因此,即使不进行 Java 开发工作,有时也可能需要安装 JDK。

c. JDE

JRE 是运行已编译 Java 程序所需的环境,主要包含以下两个部分:

  1. JVM : 也就是我们上面提到的 Java 虚拟机。
  2. Java 基础类库(Class Library):一组标准的类库,提供常用的功能和 API(如 I/O 操作、网络通信、数据结构等)。

简单来说,JRE 只包含运行 Java 程序所需的环境和类库,而 JDK 不仅包含 JRE,还包括用于开发和调试 Java 程序的工具。

d. JDK、JRE 和 JVM 的关系

20241118171004

上图展示了JDK、JRE、JVM的包含关系

从 JDK 9 开始,就不需要区分 JDK 和 JRE 的关系了,取而代之的是模块系统(JDK 被重新组织成 94 个模块)+ jlink 工具 (随 Java 9 一起发布的新命令行工具,用于生成自定义 Java 运行时映像,该映像仅包含给定应用程序所需的模块) 。并且,从 JDK 11 开始,Oracle 不再提供单独的 JRE 下载。

Java 应用可以通过新增的 jlink 工具,创建出只包含所依赖的 JDK 模块的自定义运行时镜像。Java 应用可以通过新增的 jlink 工具,创建出只包含所依赖的 JDK 模块的自定义运行时镜像。

4. 字节码

在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以, Java 程序运行时相对来说还是高效的(不过,和 C、 C++,Rust,Go 等语言还是有一定差距的),而且,由于字节码并不针对一种特定的机器,因此,Java 程序无须重新编译便可在多种不同操作系统的计算机上运行。

Java 程序从源代码到运行的过程如下图所示
20241118171418

即:Java代码通过工具带的javac编译为.class字节码文件,之后通过在JVM(JAVA虚拟机)中通过某种解释器生成机器码(机器可理解的代码),然后在不同操作系统的计算机运行。

我们需要格外注意的是 .class->机器码 这一步。在这一步 JVM 类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度会相对比较慢。而且,有些方法和代码块是经常需要被调用的(也就是所谓的热点代码),所以后面引进了 JIT(Just in Time Compilation) 编译器,而 JIT 属于运行时编译。当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。而我们知道,机器码的运行效率肯定是高于 Java 解释器的。这也解释了我们为什么经常会说 Java 是编译与解释共存的语言

20241118171753

注意:JIT是编译器,它的编译是边编译边编译

JDK、JRE、JVM、JIT 这四者的关系如下图所示:
20241118172013

5. Java 语言“编译与解释并存”的特性

高级编程语言按照程序的执行方式分为两种:

  • 编译型编译型语言 会通过编译器将源代码一次性翻译成可被该平台执行的机器码。一般情况下,编译语言的执行速度比较快,开发效率比较低。常见的编译性语言有 C、C++、Go、Rust 等等。
  • 解释型解释型语言会通过解释器一句一句的将代码解释(interpret)为机器代码后再执行。解释型语言开发效率比较快,执行速度比较慢。常见的解释性语言有 Python、JavaScript、PHP 等等。

20241118172300

为了改善解释语言的效率而发展出的即时编译技术,已经缩小了这两种语言间的差距。这种技术混合了编译语言与解释型语言的优点,它像编译语言一样,先把程序源代码编译成字节码。到执行期时,再将字节码直译,之后执行。JavaLLVM是这种技术的代表产物。

为什么说 Java 语言“编译与解释并存”?

这是因为 Java 语言既具有编译型语言的特征,也具有解释型语言的特征。因为 Java 程序要经过先编译,后解释两个步骤,由 Java 编写的程序需要先经过编译步骤,生成字节码(.class 文件),这种字节码必须由 Java 解释器来解释执行。

6. AOT编译模式

JDK 9 引入了一种新的编译模式 AOT(Ahead of Time Compilation) 。和 JIT 不同的是,这种编译模式会在程序被执行前就将其编译成机器码,属于静态编译(C、 C++,Rust,Go 等语言就是静态编译)。AOT 避免了 JIT 预热等各方面的开销,可以提高 Java 程序的启动速度,避免预热时间长。并且,AOT 还能减少内存占用和增强 Java 程序的安全性(AOT 编译后的代码不容易被反编译和修改),特别适合云原生场景。

优势

AOT 的主要优势在于启动时间、内存占用和打包体积。JIT 的主要优势在于具备更高的极限处理能力,可以降低请求的最大延迟。

缺陷

AOT 更适合当下的云原生场景,对微服务架构的支持也比较友好。但是,AOT 编译无法支持 Java 的一些动态特性,如反射、动态代理、动态加载、JNI(Java Native Interface)等。然而,很多框架和库(如 Spring、CGLIB)都用到了这些特性。如果只使用 AOT 编译,那就没办法使用这些框架和库了,或者说需要针对性地去做适配和优化。

7. Oracle JDK vs OpenJDK

Oracle JDK 和 OpenJDK 的区别:

  1. 是否开源:OpenJDK 是一个参考模型并且是完全开源的,而 Oracle JDK 是基于 OpenJDK 实现的,并不是完全开源的(个人观点:众所周知,JDK 原来是 SUN 公司开发的,后来 SUN 公司又卖给了 Oracle 公司,Oracle 公司以 Oracle 数据库而著名,而 Oracle 数据库又是闭源的,这个时候 Oracle 公司就不想完全开源了,但是原来的 SUN 公司又把 JDK 给开源了,如果这个时候 Oracle 收购回来之后就把他给闭源,必然会引起很多 Java 开发者的不满,导致大家对 Java 失去信心,那 Oracle 公司收购回来不就把 Java 烂在手里了吗!然后,Oracle 公司就想了个骚操作,这样吧,我把一部分核心代码开源出来给你们玩,并且我要和你们自己搞的 JDK 区分下,你们叫 OpenJDK,我叫 Oracle JDK,我发布我的,你们继续玩你们的,要是你们搞出来什么好玩的东西,我后续发布 Oracle JDK 也会拿来用一下,一举两得!)OpenJDK 开源项目:https://github.com/openjdk/jdk
  2. 是否免费:Oracle JDK 会提供免费版本,但一般有时间限制。JDK17 之后的版本可以免费分发和商用,但是仅有 3 年时间,3 年后无法免费商用。不过,JDK8u221 之前只要不升级可以无限期免费。OpenJDK 是完全免费的。
  3. 功能性:Oracle JDK 在 OpenJDK 的基础上添加了一些特有的功能和工具,比如 Java Flight Recorder(JFR,一种监控工具)、Java Mission Control(JMC,一种监控工具)等工具。不过,在 Java 11 之后,OracleJDK 和 OpenJDK 的功能基本一致,之前 OracleJDK 中的私有组件大多数也已经被捐赠给开源组织。
  4. 稳定性:OpenJDK 不提供 LTS 服务,而 OracleJDK 大概每三年都会推出一个 LTS 版进行长期支持。不过,很多公司都基于 OpenJDK 提供了对应的和 OracleJDK 周期相同的 LTS 版。因此,两者稳定性其实也是差不多的。
  5. 协议:Oracle JDK 使用 BCL/OTN 协议获得许可,而 OpenJDK 根据 GPL v2 许可获得许可。

既然 Oracle JDK 这么好,那为什么还要有 OpenJDK?

答:
1. OpenJDK 是开源的,开源意味着你可以对它根据你自己的需要进行修改、优化,比如 Alibaba 基于 OpenJDK 开发了 Dragonwell8:[https://github.com/alibaba/dragonwell8](https://github.com/alibaba/dragonwell8)
2. OpenJDK 是商业免费的(这也是为什么通过 yum 包管理器上默认安装的 JDK 是 OpenJDK 而不是 Oracle JDK)。虽然 Oracle JDK 也是商业免费(比如 JDK 8),但并不是所有版本都是免费的。
3. OpenJDK 更新频率更快。Oracle JDK 一般是每 6 个月发布一个新版本,而 OpenJDK 一般是每 3 个月发布一个新版本。(现在你知道为啥 Oracle JDK 更稳定了吧,先在 OpenJDK 试试水,把大部分问题都解决掉了才在 Oracle JDK 上发布)

基于以上这些原因,OpenJDK 还是有存在的必要的!

Oracle JDK 和 OpenJDK 如何选择?

建议选择 OpenJDK 或者基于 OpenJDK 的发行版,比如 AWS 的 Amazon Corretto,阿里巴巴的 Alibaba Dragonwell。

标签:Java,JDK,OpenJDK,基础知识,编译,JVM,Oracle
From: https://blog.csdn.net/qq_73340809/article/details/143863228

相关文章

  • Java学习之读取Yaml文件
    1.yaml文件示例:england:initialUrl:https://www.leisu.com/data/zuqiu/comp-82finalUrl:https://www.dszuqiu.com/league/35filePath:fileName:"英超.xlsx"spain:initialUrl:https://www.leisu.com/data/zuqiu/comp-120finalUrl:https://www.dszuqiu.......
  • Java 基础 -集合类
    集合类Java中重要的集合类有以下这些:集合类:Hashtable、HashMap、ArrayList、LinkedList、TreeMap、WeakHashMap1、ArrayListArrayList是一个有序数组,内部使用对象数组进行存储,并且有一个单独的size字段存储数组中对象的数量。transientObject[]elementData;privateint......
  • 【老白学 Java】休闲时刻 - 打造 CMD 战舰(三)
    休闲时刻-打造CMD战舰(三)文章来源:《HeadFirstJava》修炼感悟。上一篇,老白通过「硬编码」对战舰类的功能模块进行了简单测试。本篇的主要任务是继续完善战舰类并反复测试,其中涉及到几个新技术,师兄们如果感兴趣,请接着往下看。项目进度:列出必要的程序清单简单描......
  • [JavaScript]将数组按照parentId和id整理成树状结构
     JavaScriptfunctionarrayToTree(items){constrootItems=[];constlookup={};for(constitemofitems){constitemId=item.id;lookup[itemId]=item;constparentId=item.parentId;if(parentId===n......
  • javascript-表达式与操作符
    1.数组初始化二维数组letmatrix=[[1,2,3],[4,5,6],[7,8,9]];未定义元素undefinedletsparseArray=[1,,,,5];包含三个未定义元素2.对象初始化letp={x:2.3,y:-1.2};点对象包含x,y坐标letq={};空对象q.x=2.3;q.y=-1.2;赋值3.函数letsquare=function(x){returnx*x;};......
  • 前端必知必会-JavaScript For Of循环
    文章目录JavaScriptForOf循环循环遍历数组循环遍历字符串总结JavaScriptForOf循环ForOf循环JavaScriptforof语句循环遍历可迭代对象的值。它允许您循环遍历可迭代数据结构,例如数组、字符串、映射、节点列表等:语法for(variableofiterable){//要......
  • 前端必知必会-JavaScript Break and Continue
    文章目录JavaScriptBreak和ContinueBreak语句Continue语句JavaScript标签总结JavaScriptBreak和Continuebreak语句“跳出”循环。continue语句“跳过”循环中的一次迭代。Break语句break语句用于“跳出”switch()语句。break语句也可用于跳出......
  • 代码随想录算法训练营第三十二天| 509. 斐波那契数 、70. 爬楼梯、746. 使用最小花费
    理论基础总结一下就是:动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的。动态规划五部曲确定dp数组(dptable)以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组509.斐波那契数1.......
  • 代码随想录算法训练营第三十三天| 62.不同路径 、63. 不同路径 II、343. 整数拆分 。c
    62.不同路径思路:按照dp五步法分析,成功AC。代码随想录classSolution{publicintuniquePaths(intm,intn){int[][]dp=newint[m+1][n+1];dp[0][1]=1;for(inti=1;i<=m;i++){for(intj=1;j<=n;j++){......
  • Java 基础 - 字符串类
    字符串类重要的字符串类有String、StringBuilder、StringBuffer1、StringString是不可变类,内部是由final定义的字符数据构成。privatefinalcharvalue[];1.1String类的层次结构如下:String实现了比较接口,字符序列接口,序列化接口,具有以上接口的特性1.2重写了Obje......