【Java基础】基础概念与常识

Java的特点

  1. 简单易学(Java常被戏称为C+±-,在C++的基础上删减了一些难用少用的功能);
  2. 面向对象(封装、继承、多态,对比C++的半面向对象,Java是实打实的完全面向对象);
  3. 支持多线程;
  4. 支持网络编程;
  5. 高移植性(“一次编写,随处运行”,通过对各个平台虚拟机的设计,实现平台无关性);
  6. 可靠性;
  7. 安全性;
  8. 编译与解释并存。

JVM、JRE、JDK

JVM
即 Java 虚拟机(Java Virtual Machine),是运行class字节码的虚构计算机。针对不同平台(Windows、Linux、macOS)设计实现不同的 JVM,其是 Java 实现跨平台运行的关键所在。(同一份 Java 源代码编译后的class文件是相同的,经过不同平台下不同的 JVM 执行后的输出结果是一致的,“一次编译,到处运行”)。

JVM并非只有一种,只要满足 JVM 规范的都可视为 JVM。常见的 HotSpot VM 只是一种实现形式,常见的还有 J9 VM、Zing VM、 JRockit 等等。

JDKJRE
JDK(Java Development Kit),Java 开发工具箱,是功能齐全的 Java SDK。它内部包含 JRE,同时还有 javac、javadoc 与 jdb 等工具,可以创建并编译程序。
JRE (Java Runtime Environment),Java 运行时环境。其内部包含 JVM、Java类库、java 命令与其他基础构建。它虽然不能编译生成新程序,但为运行已编译的Java程序提供所需的额一切内容。

一般上讲,若存在 Java 开发上的需求就需要安装 JDK,若仅仅需要部署已开发完成的项目,那么 JRE 就足够了。特殊情况下,即使不需要开发编译同样需要安装 JDK。比如,部署依赖 JSP 模板引擎的 Web 应用,从技术上讲,服务器会将 JSP 转化成 servlet,其中涉及到 java 文件编译 class 字节码的过程,因此需要 JDK 的参与。

字节码、使用字节码的好处

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

Java 源文件运行过程

runtime
在字节码解释为机器码的过程中,JVM 类加载器首先加载字节码文件,然后通过解释器逐行解释执行,但这种方式的执行速度相对较慢。而且,存在部分代码被频繁访问调用,即所谓的热点代码。故,随后引进了 JIT 编译器(just-in-time compilation),其属于运行时编译。当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,供下次直接使用。并且机器码的运行效率高于 Java 解释器。这也解释了我们为什么经常说 Java 是编译与解释共存的语言 。

HotSpot 采用了惰性评估(Lazy Evaluation)的做法,根据二八定律,消耗大部分系统资源的只有那一小部分的代码(热点代码),而这也就是 JIT 所需要编译的部分。JVM 会根据代码每次被执行的情况收集信息并相应地做出一些优化,因此执行的次数越多,它的速度就越快。JDK 9 引入了一种新的编译模式 AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就避免了 JIT 预热等各方面的开销。JDK 支持分层编译和 AOT 协作使用。

为什么不全部使用AOT呢?

AOT(Ahead of Time Compilation) 可以提前编译节省启动时间,那为什么不全部使用这种编译方式呢?

这和 Java 语言的动态特性有千丝万缕的联系。举个例子,CGLIB 动态代理使用的是 ASM 技术,而这种技术大致原理是运行时直接在内存中生成并加载修改后的字节码文件也就是 .class 文件,如果全部使用 AOT 提前编译,也就不能使用 ASM 技术了。为了支持类似的动态特性,所以选择使用 JIT 即时编译器。

Java – “编译与解释并存”

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

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

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

Java 既有编译型语言的特征,也有解释型语言的特征。 Java 编写的程序需要先经过编译,生成字节码 .class文件,这种字节码必须由 Java 解释器来解释执行。

生成字节码文件后的执行过程及原理

  • 第一步:启动 JVM;
  • 第二步:JVM启动“类加载器classloader”。类加载器的作用:加载类。本质上类加载器负责去硬盘上找“类”对应的“字节码”文件。
  • 第三步:类加载器如果在硬盘上找不到对应的字节码文件,会报错(错误:找不到或无法加载主类)。类加载器如果在硬盘上找到了对应的字节码文件,类加载器会将该字节码文件装载到JVM中,JVM启动“解释器”将字节码解释为二进制机器码,操作系统执行机器码与硬件交互。

classpath环境变量给类加载器环境变量指路,一般情况下不需要配置,一旦配置,类加载器只会前往给定的路径下搜索字节码文件,当前路径会失效。

运行Java程序

Java 程序有两个阶段:编译阶段、运行阶段。

  • xxx.java文件里为源代码,源文件;
  • xxx.class文件为编译后生成的字节码,字节码文件。

注意:一个java源文件可以编译生成多个class文件,最终运行的是class文件。

运行 Java 程序的步骤:

  1. javac xxx.java 编译生成字节码文件;
  2. cd 切换到 xxx.class 文件所在目录;
  3. java xxx 运行程序。

Java 和 C++ 的区别

  • Java 是完全面向对象的,C++属于半面向对象;
  • Java 不提供指针来直接访问内存,程序内存更加安全;
  • Java 有自动内存管理垃圾回收机制(GC),不需要手动释放内存;
  • Java 类是单继承的,C++支持多继承
  • Java 有接口的概念,C++则没有;
  • C++ 同时支持方法重载和操作符重载,但是 Java 只支持方法重载

猜你喜欢

转载自blog.csdn.net/LogosTR_/article/details/126227773