JVM(Java Virtual Machine):Java虚拟机的缩写,是一个虚构出来的计算机,通过在实际的计算机上仿真模拟各种计算机功能实现的。
通过JVM,Java实现了平台无关性。Java程序只需要生成可以Java虚拟机上运行的目标代码(字节码),Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。
JDK(Java Development Kit):JDK是Java开发工具包,是整个Java的核心,包括了JRE,Java开发工具(javac/java/jar等)和Java基础类库。
JRE(Java Runtime Environment):是Java运行环境。包括JVM标准实现和Java核心类库。
JVM(Java Virtual Machine):是整个Java实现跨平台最核心的部分,可以运行Java语言写的软件程序。
程序计数器(pc-register),虚拟机栈(Virtual Machine stack)和本地方法栈(native method stack)是每个线程独有的,随着线程的创建而创建,随着线程的结束而销毁。方法区(method area)和堆区(heap)被所有线程所共享,在虚拟机启动的时候被创建。
虚拟机一次能够执行多个线程,JVM多线程是通过线程轮流切换并分配处理器执行时间的方式实现的。因此,为了正常的切换线程,每个线程都会有一个独立的pc,
当线程来回切换时,就知道线程上次执行到哪了。
任何时间一个线程都只有一个方法在执行,如果一个线程正在执行的是Java方法,pc记录的是正在执行的虚拟机字节码指令的地址。如果正在执行的不是Java方法,而是Native方法,pc的值为undefined。
pc的内存区域是唯一一个不会出现OutOfMemoryError的内存区域。
虚拟机栈描述Java方法执行的内存模型,每个方法在被执行的时候都会创建一个栈帧(Stack Frame),栈帧中会存储局部变量表(Local Variables),操作栈(Operand Stack),方法出口(Return Value),动态连接(Current Class Constant Pool Reference)等信息组成。每一个方法被调用的过程对应一个栈帧在虚拟机栈中从入栈到出栈的过程。
局部变量表:定义为一个数字数组,主要用于存储方法参数、定义在方法体内的局部变量,存储的数据类型包括基本数据类型,对象引用和return address类型。
局部变量表容量是在编译期间确定下来的,动态运行期间不会改变所需要的空间。最基本的存储单元是slot,64位类型(long和double)占用两个slot,其余类型占用一个slot。
操作栈:操作栈在执行字节码指令时会被用到,大部分JVM把时间花费在操作栈上,操作栈和局部变量数组会频繁的交换数据。
动态连接:动态连接控制着运行时常量池和栈帧的连接。 在Java源文件被编译到字节码文件时,所有的变量和方法引用都作为符号引用(Symbolic Reference)保存在class文件的常量池里,程序运行时将其加载进方法区的运行时常量池中,动态连接的作用就是为了将这些符号引用转换为调用方法的直接引用。
本地方法栈:本地方法栈是为了JVM运行Native方法准备的空间,由于很多Native方法都是用C语言实现的,所以它通常又叫C栈。它与Java虚拟机栈极为类似,只不过是用来描述本地方法运行过程的内存模型。
java虚拟机栈可能出现的两种类型的异常:
线程请求深度大于虚拟机允许的栈深度,会抛出StackOverflowError异常。
当虚拟机栈动态扩展无法申请到足够的空间时,会抛出OutOfMemory异常。
是用来存放对象的内存空间,几乎
所有的对象都存储在堆中。是垃圾回收的主要区域(了解一下垃圾回收),因此也被称为GC堆。堆可分为新生代,老年代。Java虚拟机规范规定,堆可以处于物理上不连续的内存空间中,但在逻辑上被视为连续的。堆的大小既可以是固定的也可以是可扩展的,如果堆无法扩展时,会抛出OutOfMemoryError异常。
主要用于存放已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码,Java虚拟机规范中定义方法区是堆的一个逻辑部分。方法区中的信息一般需要长期存在,回收一遍之后可能只有少量信息无效,主要回收的目标:对常量池的回收,对类型的卸载。Java虚拟机规范对方法区的要求比较宽松,允许固定大小,也允许动态扩展,还允许不实现垃圾回收。