深刻理解JVM(一)——基本原理

前言java

  JVM一直是java知识里面进阶阶段的重要部分,若是但愿在java领域研究的更深刻,则JVM则是如论如何也避开不了的话题,本系列试图经过简洁易读的方式,讲解JVM必要的知识点。jvm

运行流程学习

  咱们都知道java一直宣传的口号是:一次编译,处处运行。那么它如何实现的呢?咱们看下图:spa

image

  java程序通过一次编译以后,将java代码编译为字节码也就是class文件,而后在不一样的操做系统上依靠不一样的java虚拟机进行解释,最后再转换为不一样平台的机器码,最终获得执行。这样咱们是否是能够推演,若是要在mac系统上运行,是否是只须要安装mac java虚拟机就好了。那么了解了这个基本原理后,咱们尝试去作更深的研究,一个普通的java程序它的执行流程究竟是怎样的呢?例如咱们写了一段这样的代码:操作系统

public class HelloWorld { public static void main(String[] args) { System.out.print("Hello world"); } }线程

这段程序从编译到运行,最终打印出“Hello world”中间通过了哪些步骤呢?咱们直接上图:server

image

  java代码经过编译以后生成字节码文件(class文件),经过:java HelloWorld执行,此时java根据系统版本找到jvm.cfg,各位能够搜索一下本身电脑上的jvm.cfg文件在哪,它会根据你的系统版本放在不一样的位置,好比个人这个文件就在:C:\Program Files\Java\jdk1.8.0_101\jre\lib\amd64\jvm.cfg,打开看一下:对象

S{6G7J8WOT3$)72FL1DW5U7

  这是我电脑上的文件,其中-server KNOWN就表示名称为server的jvm可用。若是这时你搜索一下你电脑上jvm.dll,你就会发现它必定在你的某个server目录下,好比个人:C:\Program Files\Java\jdk1.8.0_101\jre\bin\server\jvm.dll。简而言之就是经过jvm.cfg文件找到对应的jvm.dll,jvm.dll则是java虚拟机的主要实现。接下来会初始化JVM,而且获取JNI接口,什么是JNI接口,就是java本地接口,你想啊java被编译成了class文件,JVM怎么从硬盘上找到这个文件并装载到JVM里呢,就是经过JNI接口(它还经常使用于java与操做系统、硬件交互),找到class文件后并装载进JVM,而后找到main方法,最后执行。blog

JVM基本结构递归

  可能经过上面的描述,你们对JVM运行流程有了一个粗略的认识,那么JVM内部究竟是怎么执行一个class文件的呢,也就是上图中最后一步第6步的内部细节是怎样的呢?要了解这个问题,咱们首先得看一下JVM的内部结构:

image

  从这个结构不难看出,class文件被jvm装载之后,通过jvm的内存空间调配,最终是由执行引擎完成class文件的执行。固然这个过程还有其余角色模块的协助,这些模块协同配合才能让一个java程序成功的运行,下面就详细介绍这些模板,它们也是后面学习jvm最重要的部分。

内存空间:

JVM内存空间包含:方法区、java堆、java栈、本地方法栈。

方法区是各个线程共享的区域,存放类信息、常量、静态变量。

java堆也是线程共享的区域,咱们的类的实例就放在这个区域,能够想象你的一个系统会产生不少实例,所以java堆的空间也是最大的。若是java堆空间不足了,程序会抛出OutOfMemoryError异常。

java栈是每一个线程私有的区域,它的生命周期与线程相同,一个线程对应一个java栈,每执行一个方法就会往栈中压入一个元素,这个元素叫“栈帧”,而栈帧中包括了方法中的局部变量、用于存放中间状态值的操做栈,这里面有不少细节,咱们之后再讲。若是java栈空间不足了,程序会抛出StackOverflowError异常,想想什么状况下会容易产生这个错误,对,递归,递归若是深度很深,就会执行大量的方法,方法越多java栈的占用空间越大。

本地方法栈角色和java栈相似,只不过它是用来表示执行本地方法的,本地方法栈存放的方法调用本地方法接口,最终调用本地方法库,实现与操做系统、硬件交互的目的。

PC寄存器,说到这里咱们的类已经加载了,实例对象、方法、静态变量都去了本身改去的地方,那么问题来了,程序该怎么执行,哪一个方法先执行,哪一个方法后执行,这些指令执行的顺序就是PC寄存器在管,它的做用就是控制程序指令的执行顺序。

执行引擎固然就是根据PC寄存器调配的指令顺序,依次执行程序指令。

结语

  本文主要介绍了java虚拟机运行的基本流程,以及java虚拟机内部结构。下一篇咱们将学习java内存模型以及探索java变量的可见性、有序性、指令重排等问题。