JVM与Java体系结构

文章目录

  • JVM 与 Java体系结构
  • 一、Java代码的执行流程
  • 二、字节码文件
    • 1、源码到字节码
    • 2、字节码文件
    • 3、字节码反汇编工具
      • 1)javap
      • 2)IDEA插件
  • 三、Java的跨平台性
  • 四、JDK、JRE、JVM
  • 五、虚拟机 和 Java虚拟机
    • 1、虚拟机
    • 2、Java 虚拟机
  • 六、Java虚拟机 和 操作系统
  • 七、JVM 的内存结构
  • 八、JVM 的架构模型
  • 九、JVM 的生命周期
    • 1、JVM的启动
    • 2、JVM的执行
    • 3、JVM的退出

JVM 与 Java体系结构

一、Java代码的执行流程

Java源码 --> Java编译器 --> 字节码文件 --> JVM --> 机器可执行的二进制机器码 --> 操作系统

JVM与Java体系结构_第1张图片

二、字节码文件

1、源码到字节码

Java代码的编译,会经历非常复杂的过程,这里我们先不去深入研究。我们只要关心编译之后的class字节码文件。

JVM与Java体系结构_第2张图片

2、字节码文件

.class文件是二进制文件,在文件开头有特定的文件标识(CA FE BA BE)。下面以 Student.class 的字节码信息为例:

JVM与Java体系结构_第3张图片

官方文档说明:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html

// A class file consists of a single ClassFile structure:
ClassFile {
    u4             magic;
    u2             minor_version;
    u2             major_version;
    u2             constant_pool_count;
    cp_info        constant_pool[constant_pool_count-1];
    u2             access_flags;
    u2             this_class;
    u2             super_class;
    u2             interfaces_count;
    u2             interfaces[interfaces_count];
    u2             fields_count;
    field_info     fields[fields_count];
    u2             methods_count;
    method_info    methods[methods_count];
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}

3、字节码反汇编工具

查看字节码文件如果直接使用编辑器去读,可读性极差。我们可以借助一些工具来帮我们查看类中的信息,而且还能看到反编译后的汇编指令。 通过汇编代码,我们可以深入的了解java代码的工作机制。

1)javap

javap是 JDK自带的反编译工具,可以直接使用,很方便。(可以在终端通过 javap --help 可以查看帮助信息)

$ javap --help                    
用法: javap <options> <classes>
其中, 可能的选项包括:
  -? -h --help -help               输出此帮助消息
  -version                         版本信息
  -v  -verbose                     输出附加信息
  -l                               输出行号和本地变量表
  -public                          仅显示公共类和成员
  -protected                       显示受保护的/公共类和成员
  -package                         显示程序包/受保护的/公共类
                                   和成员 (默认)
  -p  -private                     显示所有类和成员
  -c                               对代码进行反汇编
  -s                               输出内部类型签名
  -sysinfo                         显示正在处理的类的
                                   系统信息 (路径, 大小, 日期, MD5 散列)
  -constants                       显示最终常量
  --module <模块>, -m <模块>       指定包含要反汇编的类的模块
  --module-path <路径>             指定查找应用程序模块的位置
  --system <jdk>                   指定查找系统模块的位置
  --class-path <路径>              指定查找用户类文件的位置
  -classpath <路径>                指定查找用户类文件的位置
  -cp <路径>                       指定查找用户类文件的位置
  -bootclasspath <路径>            覆盖引导类文件的位置

GNU 样式的选项可使用 = (而非空白) 来分隔选项名称
及其值。

每个类可由其文件名, URL 或其
全限定类名指定。示例:
   path/to/MyClass.class
   jar:file:///path/to/MyJar.jar!/mypkg/MyClass.class
   java.lang.Object

可以根据自己的需要给javap加入参数使用,例如:

javap -p -v xxxx.class  // 显示所有类和成员的附加信息

这个是最直接,最方便的查看工具了,但是可读性没有一些插件好。

2)IDEA插件

jclasslib Bytecode viewerASM Bytecode Viewer 这两款IDEA的插件也是非常方便的。

  • jclasslib:比较强大,可以查看类中的所有信息
  • ASMPlugin:主要可以用来查看汇编指令,格式会比较友好。

jclasslib Bytecode viewer 插件的使用

JVM与Java体系结构_第4张图片

ASM Bytecode Viewer 插件的使用

JVM与Java体系结构_第5张图片

三、Java的跨平台性

Java代码 编译成 字节码文件后,可以在不同操作系统的JVM上执行(一次编译,到处执行)

JVM与Java体系结构_第6张图片

Java虚拟机只关心字节码文件,根本不关心这个字节码文件到底是使用何种编程语言编写和编译的。

JVM与Java体系结构_第7张图片

四、JDK、JRE、JVM

  • JDK(Java Development Kit)Java开发工具包
    • JRE(Java Runtime Environment)Java运行环境
      • JVM(Java Virtual Machine)Java虚拟机

JVM与Java体系结构_第8张图片

五、虚拟机 和 Java虚拟机

1、虚拟机

所谓虚拟机(Virtual Machine),就是一台虚拟的计算机。它是用来执行一系列虚拟计算机指令的软件

  • 系统虚拟机:对物理计算机的仿真,提供了一个可运行完整操作系统的软件平台。(如 Visual Box,VMware)
  • 程序虚拟机:专门为执行单个计算机程序而设计。(如 Java虚拟机)

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

2、Java 虚拟机

Java虚拟机是执行二进制字节码的虚拟计算机,拥有独立的运行机制,其运行的字节码未必由 Java 语言编译而成。

  • Java虚拟机负责装载字节码到其内部,解释/编译为对应平台上的机器指令执行。
  • 每一条字节码指令,Java虚拟机规范中都有详细定义,如怎么取操作数,怎么处理操作数,处理结果放在哪里。
  • JVM 平台的各种语言可以共享 Java 虚拟机带来的跨平台性、优秀的垃圾回收器,以及可靠的即时编译器。
  • 自动内存管理与垃圾回收功能

六、Java虚拟机 和 操作系统

Java虚拟机是执行二进制字节码的虚拟计算机,运行在操作系统之上,与硬件没有直接的交互。

JVM与Java体系结构_第9张图片

七、JVM 的内存结构

1. 类加载器(Class Loader)
		将字节码文件加载到内存中(即运行时数据区)

2. 运行时数据区(Runtime Data Area)
		JVM在运行时所管理的内存,用于存储JVM相关数据
		
3. 执行引擎(Execution Engine)
		字节码文件只是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,
		需要通过执行引擎将 java的字节码指令 转换为 底层的系统指令,再交由 CPU 去执行。

4. 本地库接口JNI(Java Native Interface)
		用于执行native修饰的方法(调用其他非java语言的本地库接口)

JVM与Java体系结构_第10张图片

  • HotSpot VM 是目前市面上高性能虚拟机的代表作之一。
  • 它采用解释器即时编译器并存的架构。

八、JVM 的架构模型

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

具体来说:这两种架构之间的区别:

基于栈式架构的特点

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

基于寄存器架构的特点

  • 典型的应用是 x86 的二进制指令集:比如传统的 PC 以及 Android 的 Davlik 虚拟机

  • 花费更少的指令去完成一项操作,性能优秀,执行更高效。

  • 指令集架构依赖于硬件,可移植性差。

  • 在大部分情况下,基于寄存器架构的指令集往往都以一地址指令、二地址指令和三地址指令为主

    而基于栈式架构的指令集却是以零地址指令为主

零地址指令:没有地址,只有操作数;一地址指令:1个地址和操作数;二地址指令:2个地址和操作数…

以 2+3 的计算流程为例:

基于栈的计算流程(以 Java 虚拟机为例):

iconst_2 //常量2入栈
istore_1
iconst_3 // 常量3入栈
istore_2
iload_1
iload_2
iadd //常量2/3出栈,执行相加
istore_0 // 结果5入栈

而基于寄存器的计算流程

mov eax,2 //将eax寄存器的值设为1
add eax,3 //使eax寄存器的值加3

小结

由于跨平台性的设计,Java 的指令都是根据栈来设计的。不同平台 CPU 架构不同,所以不能设计为基于寄存器的。

  • 优点:跨平台,指令集小,编译器容易实现
  • 缺点:性能下降,实现同样的功能需要更多的指令。

九、JVM 的生命周期

1、JVM的启动

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

2、JVM的执行

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

3、JVM的退出

有如下的几种情况:

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

你可能感兴趣的:(JVM,jvm,java,开发语言)