JVM学习记录—内存模型

 目录

什么是Java虚拟机

JVM内存模型

 程序计数器

方法区

虚拟机栈

本地方法栈


本文是基于Java8的HotSpot虚拟机分析的 

什么是Java虚拟机

众所周知,java主要特点就是平台无关性。那么如何实现平台无关性呢,答案就是用虚拟机将不同操作系统的差异隔离。Java 之所以要在虚拟机中运行,是因为它提供了可移植性。Java 代码被编译为 Java 字节码,可以在不同平台上的 Java 虚拟机实现上运行。

JVM内存模型

JVM(Java Virtual Machine)将管理的内存划分为不同功能的内存区域,如下图。

一段Java代码的运行过程:类文件编译后生成的class文件通过类加载器class loader加载到JVM中, 然后程序计数器记录目前执行到了哪一条字节码指令,然后MetaSpace存放了类的相关信息(1.8以前叫方法区),再将操作的栈帧(局部变量)存放在虚拟机栈中,创建的对象实例会存储在堆中。

其中方法区和堆是线程共享的

程序计数器和虚拟机栈、本地方法栈是线程私有的

 

public class Hello {
	public static void main(String[] args) {
		Say say=new Say();
		say.say();
	}
}
class Say{
	public void say(){
		System.out.println("hello!");
	}
}

上边这一段代码是举的一个例子,后边将以这个例子来具体说下每个内存区域都存储了什么信息。 

 程序计数器

程序计数器就是用来记录当前执行的字节码指令的位置的,也就是记录目前执行到了哪一条字节码指令。就是Hello.java文件编译后生成的.class文件的字节码文件。

方法区

在一个jvm实例的内部,类型信息被存储在一个称为方法区的内存逻辑区中。类型信息是由类加载器在类加载时从类文件中提取出来的。类(静态)变量也存储在方法区中。

类型信息
对每个加载的类型,jvm必须在方法区中存储以下类型信息: 

  • 这个类型的完整有效名 
  • 这个类型直接父类的完整有效名(除非这个类型是interface或是  java.lang.Object,两种情况下都没有父类) 
  • 这个类型的修饰符(public,abstract, final的某个子集) 
  • 这个类型直接接口的一个有序列表 

除了以上的基本信息外,jvm还要为每个类型保存以下信息: 
类型的常量池( constant pool) 
域(Field)信息 
方法(Method)和返回值信息 
除了常量外的所有静态(static)变量 

虚拟机栈

虚拟机栈是用来保存每个方法内的局部变量等数据,每个线程都有自己的虚拟机栈。如果线程中执行了一个方法,就会对这个方法创建对应的一个栈帧。栈帧里就有了这个方法的局部变量、方法出口等等数据。

堆是用来存放创建的各种对象。例如Say()对象实例,引用的图例如下。堆中有分为新生代、老年代等等,这个涉及到GC(垃圾回收)具体回头单独开一篇说。

本地方法栈

本地方法栈的功能和特点类似于虚拟机栈,均具有线程隔离的特点以及都能抛出StackOverflowError和OutOfMemoryError异常。不同的是,本地方法栈服务的对象是JVM执行的native方法,而虚拟机栈服务的是JVM执行的java方法。如何去服务native方法?native方法使用什么语言实现?怎么组织像栈帧这种为了服务方法的数据结构?虚拟机规范并未给出强制规定,因此不同的虚拟机实可以进行自由实现,我们常用的HotSpot虚拟机选择合并了虚拟机栈和本地方法栈。


下图是整个jvm完整的执行流程图 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章