jvm全称是Java Virtual Machine(java虚拟机)它之所以被称之为是虚拟的就是因为它仅仅是由一个规范来定义的抽象计算机我们平时经常使用的Sun HotSpot虚拟机只是其中一个具体的实现(另外还有BEA JRockitIBM J等等虚拟机)在实际的计算机上通过软件来实现一个虚拟计算机与VMWare等类似软件不同你是看不到jvm的它存在于内存 当启动一个Java程序时一个虚拟机实例也就诞生了当该程序关闭退出这个虚拟机实例也就随之消亡如果在同一台计算机上同时运行三个Java程序将得到三个Java虚拟机实例每个Java程序都运行于它自己的Java虚拟机实例中 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域根据《Java虚拟机规范(第版)》的规定Java虚拟机所管理的内存将会包括以下几个运行时数据区域如下图所示 图 Java虚拟机的内部体系结构 下面先对图中各部分做个简单的说明 class文件虚拟机并不关心Class的来源是什么语言只要它符合Java class文件格式就可以在Java虚拟机中运行使用Java编译器可以把Java代码编译为存储字节码的Class文件使用JRuby等其他语言的编译器一样可以把程序代码编译成Class文件 类装载器子系统负责查找并装载Class 文件到内存最终形成可以被虚拟机直接使用的Java类型 方法区在类装载器加载class文件到内存的过程中虚拟机会提取其中的类型信息并将这些信息存储到方法区方法区用于存储已被虚拟机加载的类信息常量静态变量即时编译器编译后的代码等数据由于所有线程都共享方法区因此它们对方法区数据的访问必须被设计为是线程安全的 堆存储Java程序创建的类实例所有线程共享因此设计程序时也要考虑到多线程访问对象(堆数据)的同步问题 Java栈Java栈是线程私有的每当启动一个新线程时Java虚拟机都会为它分配一个Java栈Java栈以帧为单位保存线程的运行状态虚拟机只会直接对Java栈执行两种操作以帧为单位的压栈或出栈当线程调用java方法时虚拟机压入一个新的栈帧到该线程的java栈中当方法返回时这个栈帧被从java栈中弹出并抛弃一个栈帧包含一个java方法的调用状态它存储有局部变量表操作栈动态链接方法出口等信息 程序计数器一个运行中的Java程序每当启动一个新线程时都会为这个新线程创建一个自己的PC(程序计数器)寄存器程序计数器的作用可以看做是当前线程所执行的字节码的行号指示器字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令分支循环跳转异常处理线程恢复等基础功能都需要依赖这个计数器来完成如果线程正在执行的是一个Java方法这个计数器记录的是正在执行的虚拟机字节码指令的地址如果正在执行的是Natvie方法这个计数器值则为空(Undefined) 本地方法栈本地方法栈与虚拟机栈所发挥的作用是非常相似的其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务而本地方法栈则是为虚拟机使用到的Native方法服务任何本地方法接口都会使用某种本地方法栈当线程调用Java方法时虚拟机会创建一个新的栈帧并压入Java栈然而当它调用的是本地方法时虚拟机会保持Java栈不变不再在线程的Java栈中压入新的帧虚拟机只是简单地动态链接并直接调用指定的本地方法如果某个虚拟机实现的本地方法接口是使用C连接模型的话那么它的本地方法栈就是C栈 执行引擎负责执行字节码方法的字节码是由Java虚拟机的指令序列构成的每一条指令包含一个单字节的操作码后面跟随个或多个操作数执行引擎执行字节码时首先取得一个操作码如果操作码有操作数取得它的操作数它执行操作码和跟随的操作数规定的动作然后再取得下一个操作码这个执行字节码的过程在线程完成前将一直持续 |