Java:JVM内存模型
作者:互联网
JVM内存模型
JVM内存模型可以划分为几部分?
JVM内存模型是指JVM运行时所涉及到的内存区域规范,可以划分为以下六个部分:
- 程序计数器(program counter register):存储非native方法中虚拟机字节码指令的地址,该地址用来指示线程接下来需要执行什么指令
- 虚拟机栈(vm stack):存储局部变量表1、操作数栈、动态链接、方法出口信息等,是Java非native方法执行的线程内存模型
- 本地方法栈(native method stack):与虚拟机栈一致,但只关联本地方法
- 堆(heap):存储数组及对象实例
- 方法区(method area):存储已被虚拟机加载的类型信息、常量2、静态变量、即时编译器编译后的代码缓存等
- 直接内存3(direct memory):native函数库直接分配的堆外内存,通过堆里的DirectByteBuffer对象引用
JVM内存区域分别可能出现什么问题?
- 程序计数器:不会出现什么问题
- 虚拟机栈:①StackOverflowError(线程请求的栈深大于虚拟机允许的栈深时);②OutOfMemoryError(线程申请不到足够内存的栈容量时)
- 本地方法栈:同虚拟机栈
- 堆:OutOfMemoryError(没有内存完成实例分配,且内存无法再扩展时)
- 方法区:OutOfMemoryError(无法满足新的内存分配需求时)
- 直接内存:OutOfMemoryError(设定的内存信息没有考虑到直接内存,导致各内存区域总和大于了物理内存限制,从而导致动态扩展内存时)
方法区、永久代和元空间有什么关系?
HotSpot想把垃圾收集器的分代设计扩展至方法区,用永久代来实现方法区,这样就可以垃圾收集器能够像管理堆那样来管理方法区,但其他虚拟机实现并没有采用这样的观点,因为这会导致更容易出现OOM,后来由于Oracle收购了BEA,准备融合HotSpot和JRockit时,发现两者对方法区的实现差异太大,于是从JDK6开始准备放弃永久代的概念,逐步采用本地内存来实现方法区,直到JDK8才完全废弃了永久代,改用本地内存实现的元空间来替代
局部变量表:以槽(slot)的形式存储了编译期可知的①基本数据类型(byte、short、int、long、float、double、boolean、char);②引用类型(可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或者其他与对象关联的地址);③returnAddress类型(指向了一条字节码指令的地址)。其中64位的long和double占用两个slot,其余占用一个slot ↩︎
运行时常量池:存放的是编译期生成的各种字面量与符号引用 ↩︎
直接内存:不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,而是JDK4引入的NIO中的一种基于通道与缓冲区的I/O方式关联的内存区域 ↩︎
标签:Java,虚拟机,线程,内存,JVM,OutOfMemoryError,方法 来源: https://blog.csdn.net/weixin_43647393/article/details/121968228