为了方便管理,JVM在执行Java程序的时候,会把它所管理的内存划分为多个不同的区域:
(1)class文件
class文件是Java程序编译后生成的中间代码,这些中间代码将会被JVM解释执行。
(2) 类装载子系统
类装载子系统负责把class文件装载到内存中,供虚拟机和用户自定义类装载器。其中,启动类装载器是JVM实现的一部分;用户自定义类装载器则是java程序的一部分,必须是ClassLoader类的子类。
(a)Bootstrap ClassLoader
(b)Extension ClassLoader
(c)System ClassLoader
(d)User-Defined ClassLoader
(3) 方法区
方法区用来存储被虚拟机加载的类的信息,常量,静态变量和编译器编译后的代码等数据。在类加载器加载class文件时,这些信息将被提取出来,并存储到方法区中。由于这个区域是所有线程共享的区域,所以他被设计为线程安全的。方法区中还存放了运行时的常量池,最典型的应用就是字符串常量,例如定义了如下语句String s="hello";String s1="hello";其中,"hello"是字符串常量,存储在常量池中,两个字符串引用的都是常量池中的“hello”;
(4) 堆
堆是虚拟机启动的时候创建的被所有线程共享的区域。这块区域主要用来存放对象的实例。通过new操作创建出来的对象的实例都存储在堆空间中,因此,堆就是垃圾回收机制中的重点区域。
(5) 虚拟机栈
栈是线程私有的区域,每当有新的线程创建时,就会给他分配一个栈空间。当线程结束后,栈空间就被回收,因此栈与线程拥有相同的生命周期。栈主要用来实现java语言中方法的调用和执行。每个方法在执行的时候,都会创建一个栈帧用来存储这个方法的局部变量,操作栈,动态链接和方法出口等信息。当进行方法调用时,通过压栈与弹栈操作进行栈空间的分配与释放。当一个方法被调用的时候,会压入一个新的栈帧到这个线程的栈中,当方法调用结束后,就会弹出这个栈帧,从而回收调用这个方法使用的栈空间。
(6)程序计数器
程序计数器也是线程私有的资源,JVM会给每个线程创建单独的程序计数器。他可以被看做是当前线程执行字节码的行号指示器,解释器的工作原理就是通过改变这个计数器的值来确定下一条需要诶执行的字节码指令。程序控制的流程(循环,分支,异常处理,线程恢复)都是通过这个计数器来完成的。
(7)本地方法栈
本地方法栈与虚拟机栈的作用是相似的, 唯一不同的是,虚拟机栈为虚拟机执行java方法也就是字节码服务,而本地方法栈则是为虚拟机用到的Native方法服务。navtive方法接口都会使用某本方法栈,当线程调用java方法时,JVM会创建一个新的栈帧并压入虚拟机栈。而他调用本地方法,虚拟机栈保持不变。不会再线程的虚拟机栈中压入新的帧,而是简单的动态链接并直接调用指定的本地方法。如果某个虚拟机栈实现的本地方法接口使用的是C++连接模型,那么,他的本地方法栈就是C++栈。
(8)执行引擎
执行引擎负责执行字节码。方法的字节码是由java虚拟机的指令字节组成的,每一条指令包含一个单字节的操作码,后面跟着0个或者多个操作数。当执行引擎执行字节码时,首先会取一个操作码,如果这个操作码有操作数,会接着取他的操作数。然后执行这个操作,执行完成后,会继续取得下一个操作码执行
在执行方法,JVM提供了四种指令来执行:
1)invokeestatic:调用类的static方法
2) invokevirtual:调用类的static方法
3)invokeinterface:将属性定义为接口来进行调用
4)invokespecial:调用一个初始化方法,私有方法或者父类的方法
(9)垃圾回收机制
垃圾回收机制主要作用是回收程序中不再使用的内存。