JVM 内存划分

JVM(Java 虚拟机)是Java语言实现平台无关性的具体实现,是一个虚拟的计算机设备。

以Java SE 7为标准,Java虚拟机在执行Java程序时把所管理的内存划分为若干不同的数据区域:
数据区划分
由于下面有些讲解的需要,先说明几个概念:

方法区(Method Area)[线程共享区域]

是各个线程共享区域,方法区是保存类的信息:

  • 包括常量、类的类型(Class or Interface)、访问修饰符(public private等)等;
  • 运行时常量池(Runtime Constant Pool),用于存放字段、方法信息、静态变量等(可以被多次调用)。

举个栗子:
0. main创建一个类的对象

  1. 一开始内存中是没有该类的信息的(不可能一开始就把所有类的信息加载到内存中)
  2. 类加载器(ClassLoader)首先定位到这个类的.class文件
  3. 然后读取这个文件(IO操作> ),JVM提取类信息,并将其存到方法区中。
  4. 下一次在需要创建该类的对象时,就从方法区中取该类的信息。

方法区的大小可以可以动态调整的,当无法再扩展时就抛出 OutOfMemoryError

当方法区中的某各类不在被需要(不可达时),该类的信息就被卸载,即被垃圾回收。

堆(Heap)[线程共享区域]

几乎所有的对象实例都在堆上分配,即堆空间的唯一目的就是用于存放对象。

Java虚拟机规范对其描述是:堆是所有实例、数组分配内存的运行时数据区。

也因此,堆是垃圾回收作用的空间。

目前大部分的 JVM 实现,堆的大小都是可扩展的(通过-Xmx和-Xms来控制)

如果在堆中没有内存完成实例分配,并且堆无法再扩展时,会抛出OutOfMemoryError。

本地方法栈(Native Method Stack)[线程私有]

和虚拟机栈类似,不过该部针对的不是java方法,而是native方法。

同样会抛出StackOverflowError和OutOfMemoryError。

程序计数器(Program Counter Register)[线程私有]

直译应该是PC寄存器:用于存放下一条指令所在的地址

存在两种情况:

  1. 正在执行的是Java方法,PC寄存器存的则是正在执行的编译好的字节码的指令的地址;
  2. 正在执行的是Native方法,PC寄存器为空。

该区域是唯一一个不会OutOfMemoryError的区域

虚拟机栈(VM Stack)[线程私有]

实际上虚拟机栈(VM Stack)就是按照这种方式运行的:
这里写图片描述

虚拟机栈是这样描述java方法执行的:每个方式执行时都会创建一个栈帧(Stack Frame),用于保存局部变量表操作数栈动态链接返回地址等。

每一个方法从调用直至执行完成的过程,对应着一个栈帧在vm stack中入栈到出栈的过程

局部变量表

顾名思义,局部变量表就是用于存放编译期间各种变量的值(基本类型变量)、引用对象地址、returnAddress的空间。

  • 对于基本类型的变量(8种),其值是直接保存在局部变量表中的
  • 引用类型(String,对象)是保存了一个该引用的地址,而对象的实际数据是在堆(Heap)中
  • 函数返回的地址(returnAddress),可以理解为该函数返回时应该返回到哪里
操作数栈

操作数栈中保存的也是数据,但不同的是,操作数栈的作用是实际完成函数中的具体操作,比如各种运算等。

熟悉栈的都知道,一般栈可以用来完成各种操作运算。实际上在java虚拟机中,这种运算操作就是通过栈来实现的。

为了理解局部变量表和操作数栈的区别以及两者的工作原理,可以看下图:
这里写图片描述
图中函数实现的功能是计算和。

局部变量表一开始就有一个该函数的数据变量的快照,即保存了所有变量,然后使用操作数栈来完成具体的计算操作,先是两个操作数入栈(a,b),然后出栈进行运算,运算结果再入栈,最后结果保存到局部变量表的变量c中。

由此可见,虚拟机栈也是线程私有的,其生命周期和线程相同。
关于局部变量表和操作数栈,参考博客:局部变量表和操作数栈

动态链接

动态链接即表明该栈帧指向方法区运行时常量池的引用地址。

实际上函数是保存在方法区中的运行时常量池中的,那么如何知道栈帧是属于哪一方法呢?这就是动态链接的作用了。

方法返回地址

顾名思义,就是该方法返回时返回到先前调用该方法的地址的地方,以便程序能接着执行。

异常

在Java虚拟机规范中,对于虚拟机栈规定了两种异常状况:

StackOverflowError

在虚拟机栈中和其操作数栈中,栈都是有深度限制的,若栈帧数或者操作数的数量超过了其栈的允许值,那么就会报StackOverflowError。

OutOfMemoryError

如果虚拟机栈的数量限制可以动态扩展(大部分虚拟机都支持动态扩展),而在扩展时无法申请到足够的内存,则会抛出OutOfMemoryError。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值