jvm原理和代码运行的过程

一次编译,处处运行

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

graph TD java原程序--javac编译-->java字节码 java字节码-->jvm虚拟机 jvm虚拟机--java解释-->windows机器码 jvm虚拟机--java解释-->linux机器码 windows机器码-->windows执行 linux机器码-->linux执行

java程序通过一次编译以后,将java代码编译为字节码也就是class文件,而后在不一样的操做系统上依靠不一样的java虚拟机进行解释,最后再转换为不一样平台的机器码,最终获得执行。这样咱们是否是能够推演,若是要在mac系统上运行,是否是只须要安装mac java虚拟机就好了。那么了解了这个基本原理后,咱们来看一下,一段程序是如何执行的。linux

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

这段程序从编译到运行,所经历的过程以下:windows

graph TD java源代码--class文件-->java字节码 java字节码--加载jvm.cfg文件-->加载配置 加载配置--根据jvm.cfg的配置-->加载jvm.dll文件 加载jvm.dll文件-->初始化jvm 初始化jvm-->获取JNI接口 获取JNI接口--JNI为本地方法他能够直接与操做系统交互-->操做Class文件 操做Class文件-->找到main文件执行

jvm基本结构

可能经过上面的描述,你们对JVM运行流程有了一个粗略的认识,那么JVM内部究竟是怎么执行一个class文件的呢?jvm

graph TD Class文件-->类加载器 类加载器-->内存空间 内存空间--运行时常量池-->方法区 方法区-->垃圾回收GC 内存空间--对象存储-->java堆 java堆-->垃圾回收GC 内存空间--局部变量表_栈帧_操做数-->java栈 java栈--线程结束自动释放-->线程私有 内存空间--本地方法库_C语言-->本地方法栈 本地方法栈-->线程私有 内存空间--JNI直接操做-->堆外内存

jvm内存分类介绍

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

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

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

  3. java栈是每一个线程私有的区域,它的生命周期与线程相同,一个线程对应一个java栈,每执行一个方法就会往栈中压入一个元素,这个元素叫“栈帧”,而栈帧中包括了方法中的局部变量、用于存放中间状态值的操做栈,若是java栈空间不足了,程序会抛出StackOverflowError异常.code

每一个帧表明一个方法,Java方法有两种返回方式,return和抛出异常,两种方式都会致使该方法对应的帧出栈和释放内存。对象

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

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

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

  • 静态变量+常量+类信息+运行时常量池存在方法区中,实例变量存在堆内存中。
  • 基本类型的变量和对象的引用变量都是在函数的栈内存中分
相关文章
相关标签/搜索