JVM内存分布

概述

Java虚拟机(Java Virtual Machine)是Java语言write once,run anywhere的基础之一。主要的功能是通过Class Loader来加载Java程序,以及自动管理内存,大部分情况下程序员不需要关心何时释放内存,回收垃圾等操作。
根据JVM规范,Java虚拟机的内存分布主要有以下五大区域。(不同的虚拟机在这个规范的基础上的实现不同,比如Hot Spot在jdk7使用了永久代来实现方法区,而在jdk8中移除了永久代,将方法区放到了元空间(meta-space))
JVM内存分布_第1张图片
JVM结构图

堆(Heap):

堆是Java虚拟机管理的内存中最大的一块区域,Java堆是所有线程共享的区域,在虚拟机启动的时候创建。堆的作用是用来存放几乎所有的对象实例(虚拟机的逃逸分析和TLAB会根据分析,将对象实例分配到栈上,而不是堆上,减轻堆的同步负载和内存分配压力)。
Java堆是垃圾器管理的主要区域,因此也被称为GC(garbage collect)堆。当要给新的实例分配内存空间的时候,堆空间不足会抛出OOM异常。

虚拟机栈(VM Stack):

Java内存中,划分最粗糙的方法将是堆栈。这里的栈内存也就是虚拟机栈。虚拟机栈是线程私有的(线程私有的意思就是,每个线程都有一个自己的虚拟机栈)。虚拟机栈执行方法的时候,会为每一个方法创建一个栈帧,用于存放局部变量、操作数栈、动态链接、方法出口等信息。每一个方法的调用过程,在虚拟机中就是一个栈帧的一次入栈出栈。所以在用递归的方法来处理量很大的数据的时候,就会 导致StackOverFlowError。
局部变量表中存放了几种类型的数据:
1. 基本数据类型(boolean、int、double、byte…)
2. 对象引用,也就是局部变量,但是这里存的只是引用(对象的起始地址,句柄或者其他与对象相关的位置),不是对象实例。
3. returnAddress,Java的三种原始数据类型(数值、boolean、returnAddress)之一。用来保存当前执行指令的下一条指令,用 来后续执行。

方法区(Method):

方法区也是用于线程共享的区域,用来存储已经被加载的类信息,常量、静态变量、即时编译器编译后的代码数据。
在HotSpot虚拟机中(Sun JDK和OpenJDK中所带的虚拟机,也是目前使用范围最广的Java虚拟机),方法区的实现在不同版本的jdk中实现有所不同。在JDK7中,HotSpot虚拟机使用永久代来实现方法区,而在JDK8之后移除了永久代,并将方法区移入了meta-space中。

本地方法栈(Navitive Method Stack):

功能和虚拟机栈作用非常相似,虚拟机栈执行的是Java字节码,而本地方法栈执行的是Native方法。

程序计数器(Programmer Counter Register):

程序计数器是一小块内存区域,也是线程私有的。用来储存当前线程执行的字节码的行号。
Java多线程是通过线程轮流切换并分配给处理器执行的方式实现的。所以如果当前线程切换后,要想恢复到正确的位置,就需要程序计数器了。
如果当前线程执行的方法是Java方法,那程序计数器保存的就是字节码指令的地址,如果执行的是Native方法,计数器的值就为空(Undefind)。

你可能感兴趣的:(JVM)