了解 JVM

68 阅读7分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

计算机系统体系对我们来说越来越远, 在不了解底层实现的前提下, 通过高级语言很容易编写程序代码. 但事实上计算机并不认识高级语言. 高级语言必须翻译成机器指令才能被计算机识别运行.

字节码

我们平时说的字节码, 指的是用 Java 编译成的字节码. 准确的说, 任何能在 jvm 平台上执行的字节码的格式都是一样的. 所以应该统称为:jvm 字节码.

不同的编译器, 可以编译出相同的字节码文件, 字节码文件也可以在不同的 JVM 上运行.

JVM 与 Java 语言并没有必然的联系, 它只与特定的二进制文件格式 Class 文件格式所关联, Class 文件中包含了 Java 虚拟机指令集(或者称为字节码, Bytecodes)和符号表, 还有一些其他辅助信息.

跨平台 跨语言

Java 是一门可以跨平台的语言. 因为字节码文件的存在,支持其在多种操作系统上运行。

而 JVM 是一个跨语言的平台. 不论是哪种编程语言,只要可以编译为指定格式的字节码文件,都可以在 JVM 上运行。

随着 Java7 的发布, JVM 基本实现了在 JVM 平台上运行非 Java 语言编写的程序.

JVM 根本不关心运行在其内部的程序到底是使用何种编程语言编写的, 它只关心字节码文件. 即 JVM 拥有语言无关性, 并不与 Java 绑定。

只要其他编程语言的编译结果,满足并包含 JVM 的内部指令集, 符号表以及其他辅助信息, 它就是一个有效的字节码文件, 就能被 JVM 识别并装载运行.

一句话总结 : JVM 只认字节码, 不认语言

多语言混合编程

Java 平台上的多语言混合编程正成为主流, 通过特定领域的语言去解决特定领域的问题,是当前软件开发应对复杂的项目需求的一个方向.

试想一下, 在一个项目之中, 每个应用层都使用不同的编程语言来完成, 而且, 接口对每一层的开发者都是透明的, 各种语言之间的交互不存在任何困难, 就像使用自己语言的原生 API 一样方便, 因为它们最终都运行在一个虚拟机之上.

对这些运行于 JVM 之上, Java 之外的语言, 来自系统级的, 底层的支持正在迅速增强, 以 JSR-292 为核心的一系列项目和功能改进, 推动 JVM 从 Java 语言的虚拟机向多语言虚拟机的方向发展.

Java 虚拟机

虚拟机

虚拟机(Virtual Machine), 就是一台虚拟的计算机. 它是一个软件, 用来执行一系列虚拟计算机指令. 大体上, 虚拟机可以分为系统虚拟机程序虚拟机.

  • 大名鼎鼎的 Visual Box, VMware 就属于系统虚拟机, 它们完全是对物理计算机的仿真, 提供了一个可运行完整操作系统的软件平台.
  • 程序虚拟机的典型代表就是 Java 虚拟机, 它专门为执行单个计算机程序而设计, 在 Java 虚拟机中执行的指令我们称为 Java 字节码指令.

无论是系统虚拟机还是程序虚拟机, 在上面运行的软件都被限制于虚拟机提供的资源中.

Java 虚拟机

Java 技术的核心就是 Java 虚拟机, 因为所有的 Java 程序都运行在 Java 虚拟机内部. Java 虚拟机是一台执行 Java 字节码的虚拟计算机, 它拥有独立的运行机制.

JVM 平台的各种语言可以共享 Java 虚拟机带来的跨平台性, 优秀的垃圾回器, 以及可靠的即时编译器.

作用 : Java 虚拟机就是二进制字节码的运行环境, 负责装载字节码到其内部, 解释/编译为对应平台上的机器指令执行. 每一条 Java 指令, Java 虚拟机规范中都有详细定义, 如怎么取操作做数, 怎么处理操作数, 处理结果放在哪里.

特点:一次编译, 到处运行,自动内存管理,自动垃圾回收功能.

JVM 的位置

JVM 是运行在操作系统之上的软件, 它与硬件没有直接的交互.

JVM 架构模型

Java 编译器输入的指令流基本上是一种基于栈的指令集架构, 另外一种指令集架构则是基于寄存器的指令集架构.

① 基于栈式架构的特点 :

  • 设计和实现更简单, 适用于资源受限的系统;
  • 避开了寄存器的分配难题:使用零地址指令方式分配.
  • 指令流中的指令大部分是零地址指令, 其执行过程依赖于操作栈. 指令集更小, 编译器容易实现.
  • 不需要硬件支持, 可移植性更好, 更好实现跨平台

② 基于寄存器架构的特点 :

  • 典型的应用是 x86 的二进制指令集:比如传统的 PC 以及 Android 的 Dav1ik 虚拟机.
  • 指令集架构则完全依赖硬件, 可移植性差
  • 性能优秀和执行更高效;
  • 花费更少的指令去完成一项操作.
  • 在大部分情况下, 基于寄存器架构的指令集往往都以一地址指令, 二地址指令和三地址指令为主, 而基于栈式架构的指令集却是以零地址指令为主.

由于跨平台性的设计, Java 的指令都是根据栈来设计的. 不同平台 CPU 架构不同, 所以不能设计为基于寄存器的. 优点是跨平台, 指令集小, 编译器容易实现, 缺点是性能下降, 实现同样的功能需要更多的指令.

JVM 生命周期

① 虚拟机的启动 :

  • Java 虚拟机的启动是通过引导类加载器(bootstrap class loader)创建一个初始类(initialclass)来完成的, 这个类是由虚拟机的具体实现指定的.

② 虚拟机的执行 :

  • 一个运行中的 Java 虚拟机有着一个清晰的任务:执行 Java 程序.
  • 程序开始执行时他才运行, 程序结束时他就停止.
  • 执行一个所谓的 Java 程序的时候, 真真正正在执行的是一个叫做 Java 虚拟机的进程.

③ 虚拟机的退出 :

  • 程序正常执行结束,自动退出.
  • 程序在执行过程中遇到了异常或错误,而异常终止.
  • 由于操作系统出现错误而导致 Java 虚拟机进程终止.
  • 某线程调用 Runtime 类或 system 类的 exit 方法, 或 Runtime 类的 halt 方法, 并且 Java 安全管理器也允许这次 exit 或 halt 操作.
  • 除此之外, JNI(Java Native Interface)规范描述了用 JNI Invocation API 来加载或卸载 Java 虚拟机时, Java 虚拟机的退出情况.

JVM 发展历程

  • 早在1996年Java1.0版本的时候, Sun公司发布了一款名为 Sun Classic VM 的 Java 虚拟机, 它同时也是世界上第一款商用 Java 虚拟机, 其在 JDK1.4 时完全被淘汰.
  • Exact M,在 JDK1.2 时发布,具备现代高性能虚拟机的维形
  • Hotspot VM,JDK1.3 时, HotSpot VM 成为默认虚拟机,目前Hotspot占有绝对的市场地位, 称霸武林. 现在仍在广泛使用的JDK8, 默认的虚拟机就是 HotSpot
  • BEA 的 JRockit.
  • IBM 的 J9,广泛用于 IBM 的各种 Java 产品.