1、什么是JVM?

   JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java语句的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使用Java语言编译程序只需要生成在Java虚拟机上运行的目标代码(字节码)。就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解析成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行"的原因。常用的虚拟机有VMWare,Virtual Box,Java Virtual Machine

2、JVM主要组成部分

java核心机制 java虚拟机 简述java虚拟机工作原理_java核心机制 java虚拟机

JVM有三个主要的子系统构成:Class Loader(类加载器子系统)、Runtime Data Area(运行时数据区)、执行引擎(ExecutionEngine)

Java虚拟机运行时数据区的图(JVM内存模型)

java核心机制 java虚拟机 简述java虚拟机工作原理_JVM_02

1、方法区:

   方法区和java堆一样,是各个线程共享的内存区域,用于存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译的代码等数据。通常被开发人员成为“永久带”。这个区域的内存回收的目标就是针对常量池的回收和对类型的卸载,也是较为难处理的部分。

2、堆:

java核心机制 java虚拟机 简述java虚拟机工作原理_局部变量_03

   堆是java虚拟机中内存中最大的一块,被所有线程共享的一块内存区域,在虚拟机创建时创建。作用就是存放对象实例,所有的对象的实例都需要在这里分配内存。几乎所有的对象实例和对象数组都需要在堆上分配。是java虚拟机内存回收的管理的重要区域,因此也别称为“GC堆,可被分为:新生代和老年代;Eden空间、From Survivor空间、To Survivor空间。如果堆中没有内存完成实例分配,并且堆也无法扩展时,则抛出OutOfMemoryError异常。
   1)、新生代(Young Generation):年轻代主要存放新创建的对象,内存大小相对会比较小,垃圾回收会比较频繁。年轻代分成Eden空间、From Survivor空间、To Survivor空间。当对象在堆创建时,将进入年轻代的Eden空间。垃圾回收器进行垃圾回收时,扫描Eden空间和From Survivor空间,如果对象仍然存活,则复制到To Survivor空间。如果To Survivor空间已经满,则复制到老年代(Old Generation)。同时扫描Survivor空间是,如果对象已经经过了几次的扫描仍然存活,JVM认为其为一个持久化对象,则将其移到老年代(Old Generation)。扫描完毕后,JVM将Eden空间和From Survivor空间清空,然后交换From Survivor空间和To Survivor的角色,这样做主要的目的是为了减少内存碎片的产生。
   2)、老年代(Old Generation):老年代主要存放JVM认为生命周期比较长的对象(进过几次的年轻代的垃圾回收后仍然存在),内存大小相对会比较大,垃圾回收也相对没有那么频繁。老年代主要采用压缩的方式来避免内存碎片。
   3)、元空间(MetaData Space):JDK8之前叫“永久代”
3、虚拟机栈:
   java虚拟机栈也是线程私有,与线程的生命周期一致,在执行每个方法都会创建一个Stack Frame用于存储局部变量表、操作数栈、动态链接、方法出口信息。每一个方法从开始执行到结束,对应一个Stack Frame在虚拟机值栈中从入栈和出栈的过程。如果线程请求的栈深度大于虚拟机所允许的深度,就会出现StackOverFlowException。如果允许动态扩展,在扩展的过程中,如果无法申请到足够的内存,则会抛出OutOfMemoryException异常。
4、本地方法栈:
   本地方法栈和java虚拟机栈的作用类似,同样式线程私有,它们之间的区别不过是虚拟机栈为java方法服务,而本地方法栈为虚拟机使用到的Native方法提供服务。在JVM规范中,并没有对本地方法发展的具体实现方法以及数据结构作强制规定,虚拟机可以自由实现它。在HotSopt虚拟机中直接把本地方法栈和java栈和二为一。本地方法栈也会抛出StackOverFlowException和OutOfMemoryException异常。
5、程序计数器:
   程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器(也称为PC寄存器)。在虚拟机的概念模型里,字节码解析器工作是就是通过改变这个计数器的值来选取下一条需要执行的字节码指令、分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计算器来完成。在多线程中,每个线程都有一个独立的程序计数器,每个线程的程序计数器之间互不影响,即"线程私有"。同时,程序计数器是Java虚拟机规范中唯一一个没有规定OutOfMemoryError的区域。

3、线程

   java虚拟机栈描述的是Java方法执行时候的内存概念模型,每一个方法在执行的时候都会创建一个栈帧,用来创建这个方法的操作数栈,局部变量表,方法出口,动态链接等信息,每一个方法在调用和结束的过程就对应了一个栈帧在虚拟机栈中入栈到出栈的过程,Java虚拟机栈是一个后进先出栈,靠后执行的方法会优先完成,后面进入虚拟机栈的栈帧优先被出栈的过程。

java核心机制 java虚拟机 简述java虚拟机工作原理_Java_04

   1)、Java虚拟机栈中存储的内容,它被用于存储数据和部分过程结果的数据结构,同时也被用来处理动态链接、方法返回值的异常分派。
   2)、一个完整的栈帧包含:局部变量表、操作数栈、动态链接信息、方法正常完成和异常完成信息。
   3)、Java局部变量表是栈帧重要组中部分之一,他主要保存函数的参数以及局部的变量信息。局部变量表中的变量作用域是当前调用的函数。函数调用结束后,随着函数栈帧的销毁,局部变量表也随之销毁,释放空间。由于局部变量表存在栈帧中。所以,如果函数参数和局部变量比较多,会使函数参数和局部变量比较多,会使的局部变量表膨胀,每一次调用会占用很多的栈空间。最终结局就是栈空间内存一定的情况下调用的次数减少。
   4)、所谓操作数是指那些被指令操作的数据。当需要对参数操作时如c=a+b,就将即将被操作的参数压栈,如将a和b压栈,然后由操作指令将它们弹出,并执行操作。虚拟机将操作数栈作为工作区。Java虚拟机没有寄存器,所有参数传递、值返回都是使用操作数栈来完成的。

4、Java内存模型是什么?

   Java内存模型规定和指引Java程序在不同的内存框架、CPU和操作系统间有确定性地行为。它在多线程的情况下尤其重要。Java内存模型对一个线程所做的变动能被其它线程可见提供了保证,它们之间是先行发生关系。这个关系定义了一些规则让程序员在并发编程是思路更清晰。比如,先行发生关系确保了:
   1)、线程内的代码能够按先后顺序执行,这被称为程序次序规则。
   2)、对于同一个锁,一个解锁操作一定要发生在时间上后发生的另一个锁定操作之前,也叫做管程锁定规则。
   3)、前一个对volatille的写操作在后一个volatile的读操作之前,也叫volatile变量规则。
   4)、一个线程内的任何操作必需在这个线程的start()调用之后,也叫作线程启动规则。
   5)、一个线程的所有操作都会在线程终止之前,线程终止规则。
   6)、一个对象的终结操作必须在这个对象构造完成之后,也叫对象终结规则。
   7)、可传递性。