Java教程

Java:JVM内存模型

本文主要是介绍Java:JVM内存模型,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

JVM内存模型

  • JVM内存模型可以划分为几部分?
  • JVM内存区域分别可能出现什么问题?
  • 方法区、永久代和元空间有什么关系?

JVM内存模型可以划分为几部分?

JVM内存模型是指JVM运行时所涉及到的内存区域规范,可以划分为以下六个部分:

  1. 程序计数器(program counter register):存储非native方法中虚拟机字节码指令的地址,该地址用来指示线程接下来需要执行什么指令
  2. 虚拟机栈(vm stack):存储局部变量表1、操作数栈、动态链接、方法出口信息等,是Java非native方法执行的线程内存模型
  3. 本地方法栈(native method stack):与虚拟机栈一致,但只关联本地方法
  4. 堆(heap):存储数组及对象实例
  5. 方法区(method area):存储已被虚拟机加载的类型信息、常量2、静态变量、即时编译器编译后的代码缓存等
  6. 直接内存3(direct memory):native函数库直接分配的堆外内存,通过堆里的DirectByteBuffer对象引用

JVM内存区域分别可能出现什么问题?

  1. 程序计数器:不会出现什么问题
  2. 虚拟机栈:①StackOverflowError(线程请求的栈深大于虚拟机允许的栈深时);②OutOfMemoryError(线程申请不到足够内存的栈容量时)
  3. 本地方法栈:同虚拟机栈
  4. 堆:OutOfMemoryError(没有内存完成实例分配,且内存无法再扩展时)
  5. 方法区:OutOfMemoryError(无法满足新的内存分配需求时)
  6. 直接内存:OutOfMemoryError(设定的内存信息没有考虑到直接内存,导致各内存区域总和大于了物理内存限制,从而导致动态扩展内存时)

方法区、永久代和元空间有什么关系?

HotSpot想把垃圾收集器的分代设计扩展至方法区,用永久代来实现方法区,这样就可以垃圾收集器能够像管理堆那样来管理方法区,但其他虚拟机实现并没有采用这样的观点,因为这会导致更容易出现OOM,后来由于Oracle收购了BEA,准备融合HotSpot和JRockit时,发现两者对方法区的实现差异太大,于是从JDK6开始准备放弃永久代的概念,逐步采用本地内存来实现方法区,直到JDK8才完全废弃了永久代,改用本地内存实现的元空间来替代


  1. 局部变量表:以槽(slot)的形式存储了编译期可知的①基本数据类型(byte、short、int、long、float、double、boolean、char);②引用类型(可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或者其他与对象关联的地址);③returnAddress类型(指向了一条字节码指令的地址)。其中64位的long和double占用两个slot,其余占用一个slot ↩︎

  2. 运行时常量池:存放的是编译期生成的各种字面量与符号引用 ↩︎

  3. 直接内存:不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,而是JDK4引入的NIO中的一种基于通道与缓冲区的I/O方式关联的内存区域 ↩︎

这篇关于Java:JVM内存模型的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!