JVM内存模型

JVM运行时数据区

在Java程序运行的时候,Java虚拟机会把它管理的内存划分为多个不同的数据分区,每个分区有各自的用途、以及各自的创建和销毁时间。这些运行时划分的分区总体上可分为线程共享的部分和线程私有的部分。

一、线程共享的部分

1、Java堆

Java堆在虚拟机启动时创建,是虚拟机所管理的内存中最大的一块分区,用于存放对象实例,Java程序中几乎所有的对象实例都在堆中分配内存。之所以说是几乎,是由于当前即时编译技术的进步,尤其是逃逸分析技术的日渐强大,栈上分配、标量替换优化手段等的出现使部分实例对象可以不分配在堆中。

在基于分代收集理论的虚拟机中,堆通常会被划分为新生代、老年代、永久代,新生代中又划分为Eden、From Survivor、To Survivor三个区。

可以通过-Xmx设置堆的最大值,-Xms设置堆的最小值,如果Java堆中没有剩余内存用于分配新的对象实例,将会抛出OutOfMemoryError异常。

2、方法区

方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码缓存等数据。在jdk7以前使用永久代实现方法区,而jdk8及以后就采用的元空间实现方法区。
在方法区中垃圾收集行为相对少见,回收主要目标是针对常量池的回收和对类型的卸载。
如果方法区剩余内存不能满足新的内存分配需求,会抛出OutOfMemoryError异常。

运行时常量池
运行时常量池是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项常量池表信息,用于存放编译期生成的各种字面量与符号引用,常量池信息表中的内容将在类加载后存放到方法区的运行时常量池中。运行期间也可以将新的常量放入常量池中,如使用String类的intern()方法,会将字符串放入常量池中并返回引用

二、线程私有的部分

1、程序计数器

程序计数器是一块较小的内存空间,每个线程都有程序计数器,它的作用相当于指明当前线程所执行的字节码指令的地址,如果正在执行的是本地方法,则这个计数器的值应为空。

2、Java虚拟机栈

Java虚拟机栈描述的是Java方法执行的线程内存模型,它的生命周期与线程相同,也就是说每一个线程都拥有一个虚拟机栈,当方法被执行的时候,Java虚拟机栈会同步创建一个栈帧,这个栈帧就用于存放该方法中的局部变量表、操作数栈、动态连接、方法出口等信息,每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
局部变量表存放了编译期可知的各种Java虚拟机基本数据类型、reference类型和returnAddress类型(指向一条字节码指令的地址),这些数据类型在局部变量表中的存储空间以局部变量槽来表示。局部变量表所需的内存空间在编译期间完成分配。

3、本地方法栈

本地方法栈与Java虚拟机栈的作用类似,区别在于本地方法栈是为虚拟机使用到本地方法时服务(本地方法即为其他语言编写封装的方法),而Java虚拟机栈为虚拟机执行Java方法服务。

三、直接内存

直接内存是由于使用如Native函数库等直接分配的堆外内存,直接内存并不是虚拟机运行时数据区的一部分。直接内存的分配不会受到Java堆大小的限制,但肯定还是会受到物理机总内存限制,当不足以满足Java程序新的内存分配需求时也会导致OutOfMemoryError异常。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值