Java虚拟机是一台执行Java字节码的虚拟计算机,它拥有独立的运行机制,其运行的Java字节码也未必由Java语言编译而成。
Java技术的核心就是Java虚拟机(JVM,Java Virtual Machine),因为所有的Java程序都运行在Java虚拟机内部。
- 作用
Java虚拟机就是二进制字节码的运行环境,负责装载字节码到其内部,编译为对应平台上的机器指令执行。每一条Java指令,Java虚拟机规范中都有详细定义,如怎么取操作数,怎么处理操作数,处理结果放在哪里。 - 特点
▶一次编译,到处运行。
▶自动内存管理。
▶自动垃圾回收。
JVM是运行在操作系统之上的,它与硬件没有直接的交互。不同的操作系统装的JVM是有区别的。
类装载器子系统将字节码文件加载到内存中生成Class对象然后在执行引擎解释运行。这个过程中涉及到加载->链接->初始化。在内存中多线程共享堆和方法区。每个线程独有一份Java虚拟机栈,本地方法栈和程序计数器。
1程序计数器:每个线程一块,指向当前线程正在执行的字节码代码的行号。如果当前线程执行的是navtive方法,则其值为null。
2Java虚拟机栈:线程私有,每个线程对应一个Java虚拟机栈,其生命周期与线程同进同退。每个Java方法在被调用的时候都会创建一个栈帧,并入栈。一旦完成调用,则出栈。所有的栈帧都出栈后,线程也就完成了使命。
3本地方法栈:功能与Java虚拟机栈十分相同。区别在于,本地方法栈为虚拟机使用到的native方法服务。
4堆:堆是JVM内存占用最大,管理最复杂的一个区域。堆是所有线程共享的一块区域,主要用来存放对象和数组。在Java虚拟机规范中有描述:所有的对象实例和数组都要在堆上分配。但是随着JIT(JUST-IN-TIME)编译器的发展与逃逸分析技术的逐渐成熟,并不是所有对象都只在堆上分配了,比如:随着逃逸分析技术的逐渐成熟,在即使能被回收的对象也有肯能会在虚拟机栈上分配。
1.7后,字符串常量池从永久代中剥离出来,存放在堆中。堆有自己进一步的内存分块划分。
5执行引擎:分为解释器、JIT编译器(后端编译器)【编译反复执行的热点代码】和垃圾回收器。操作系统只能识别机器指令,但是字节码指令不等同于机器指令。要想字节码文件能够解释执行就需要借助执行引擎,把高级语言翻译成机器语言。
Java代码的执行流程
JVM的架构模型
Java编译器输入的指令流基本上是一种基于栈的指令集架构。
基于栈式架构的特点:
▶设计和实现简单(Java程序的运行通过方法实现,每执行一个方法可以理解为一个入栈操作,栈顶就是当前正在执行的方法,方法执行完做一个出栈的操作就可以了),适用于资源受限的系统(嵌入式设备、小型设备)
▶避开了寄存器的分配难题;使用零地址指令(没有地址,只有操作数)方式分配
▶指令流中的指令大部分是零地址指令,其执行流程依赖于操作栈(只需要操作栈顶)。指令集更小(字节码文件中每8位字节进行对齐),编译器容易实现
▶不需要硬件支持,可移植性更好,更好实现跨平台(因为栈是内存层面的)
▶缺点是性能下降,实现同样的功能需要更多的指令
JVM的生命周期
虚拟机的启动
Java虚拟机的启动时通过引导类加载器(bootstrap class loader)创建一个初始类(initial class)来完成的,这个类由虚拟机的具体实现指定的。
虚拟机的执行
▶一个运行中的Java虚拟机的任务是执行Java程序
▶程序开始执行时他才运行,程序结束他就停止
▶执行一个所谓的Java程序的时候,真真正正在执行的是一个叫做Java虚拟机的进程
虚拟机的退出
▶程序正常执行结束
▶程序在执行过程中遇到了异常或错误而异常终止
▶由于操作系统出现错误从而导致Java虚拟机进程终止
▶某线程调用调用Runtime类或System类的exit方法,或Runtime类的halt方法,并且Java安全管理器也允许这次exit或halt操作(主动结束程序执行)
▶Java本地方法接口(JNI-Java Native Interface)规范中描述的用JNI Invocation API来加载或卸载Java虚拟机时,Java虚拟机的退出情况