概述
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。
Java运行机制
-
Java语言比较特殊, 由Java编写的程序需要经过编译步骤,但这个编译步骤不会产生特定平台的机器码,而是生成一种与平台无关的字节码(也就是.class文件)。这种字节码不是可执行性的,必须使用Java解释器来解释执行。因此可以认为: Java语言既是编译型语言,也是解释型语言。 或者说,Java语言既不是纯粹的编译型语言,也不是纯粹的解释型语言。
Java程序的执行过程,必须经过先编译,后解释两个步骤。 -
Java语言里,负责解释执行字节码文件的是Java虚拟机,即JVM(Java Virtual Machine)。JVM是可以运行Java字节码文件的虚拟计算机。所有平台上的JVM向编译器提供相同的编程接口,而编译器只需要面向虚拟机,生成虚拟机能理解的代码,然后由虚拟机来解释执行。在一些虚拟机的实现中,还会将虚拟机代码转换成特定系统的机器码执行,从而提高运行效率。
-
当使用Java编译器编译Java程序时,生成的是与平台无关的字节码,这些字节码不面向任何具体的平台。 只面向JVM。不同平台上的JVM都是不同的,但他们都提供了相同的接口。JVM是Java程序跨平台的关键部分。只要为不同的平台实现了相应的虚拟机,编译后的Java字节码就可以在该平台上运行。显然,相同的字节码程序需要在不同的平台上运行,这几乎是“不可能的”, 只有通过中间的转换器才可以实现,JVM就是这转换器。
JVM
JVM是一个抽象的计算机,和实际的计算机一样,它具有指令集并使用不同的存储区域。它负责执行指令,还要管理数据、内存和寄存器。
Oracle公司制定的Java虚拟机规范在技术上规定了JVM的统一标准,具体定义了如下细节:
- 指令集
- 寄存器
- 类文件的格式
- 栈
- 垃圾回收堆
- 存储区
Oracle公司制定的这些规范的目的是为了提供统一的标准,最终实现了Java程序的平台无关性。
当调用java命令来运行某个Java程序时,该命令会启动一个Java虚拟机进程,不管该Java程序有多么复杂,该程序启动了多少个线程,它们都处于该java虚拟机进程里。
同一个JVM所有线程、所有变量都处于同一个进程里,它们都使用该JVM进程的内存区。
当出现下面几种情况时,JVM进程将被终止:
- 程序运行到最后正常结束
- 程序运行到使用System.exit()或Runtime.getRuntime().exit()代码处结束程序
- 程序运行过程中遇到未捕获的异常或错误而结束
- 程序所在平台强制结束了JVM进程
当Java程序运行结束时,JVM进程结束,该进程在内存中的状态将会丢失。
类加载的时机
类从被加载到虚拟机内存中,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段。
其中验证、准备、解析3个部分统称为连接(Linking)。
图中,加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,而解析阶段则不一定:它在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言的运行时绑定(也称为动态绑定或晚期绑定)。