Java内存区域

本文最后更新于:2022年7月29日 下午

相对于C、C++程序员来说Java程序员应该是很幸福的,他们不需要管理自己的内存,而全部交由JVM来控制,它使得我们能够更加专注于程序功能点的开发而不去维护内存,天下苦NPE久矣,但是一旦出现内存泄漏和溢出方面的问题,如果你不了解JVM具体的运行原理,那么排查错误将是一个非常非常艰难的任务,并且如果你在书写Java程序的时候不知道它一个底层的运行原理,那么你很难书写良好的代码。

运行时数据区域

Java虚拟机咋执行Java程序的时候会把它管理的内存划分为若干个不同的数据区域

无特殊说明介绍的都是HotSpot虚拟机
并且JDK版本默认是1.8及以上

JVM运行时数据区域示意图

其中线程私有的有

  1. 程序计数器
  2. 虚拟机栈
  3. 本地方法栈

线程共享的的有

  1. 方法区
  2. 直接内存(即非运行时数据区的一部分)

下面让我们来针对这些内存一个一个的分析

程序计数器

  1. 什么是程序计数器

程序计数器是当前线程正在执行的字节码的地址,它是线程隔离的,其执行原理为字节码解释器读取内存中的字节码,按照顺序读取字节码指令,读取一个指令就把它翻译为一个固定的操作。

  1. 为什么需要程序计数器

在单线程来看可有可无,但是在多线程看来需要保存当前线程所执行的位置

  1. 程序计数器的特点
    1. 程序计数器是线程隔离的
    2. 程序计数器占用的内存空间非常小,可以忽略不计
    3. 程序计数器是java虚拟机规范中唯一一个没有规定任何OutOfMemoryError的区域
    4. 执行native本地方法时,程序计数器的值为空。原因是native方法是java通过jni调用本地C/C++库来实现,非java字节码实现,所以无法统计

Java虚拟机栈

Java虚拟机栈也是线程私有的,它的生命周期和线程周期相同,它描述了Java方法执行时的内存模型,每一次方法的调用的数据都是通过栈传递的。

Java虚拟机栈是有一个一个的栈帧组成,每个栈帧都拥有局部变量表、操作数栈、动态链接、方法出口信息。

Java虚拟机栈会出现两种错误:StackOverFlowErrorOutOfMemoryError

  • StackOverFlowError:如果Java虚拟机栈的内存大小不允许动态扩展,那么当线程请求栈的深度超过当前Java虚拟机最大深度的时候就会报错
  • OutOfMemoryError:如果Java虚拟机堆没有空闲内存,并且垃圾回收器也无法提供更多内存的话,就会抛出OutOfMemoryError错误

本地方法栈

本地方法栈和Java虚拟机栈的作用相似,区别为:Java虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务,在HotSpot虚拟机中,Java虚拟机栈和本地方法栈合二为一。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!