Java内存管理—虚拟机运行时数据区域

概述

C/C++开发人员在内存管理方面最有最高统治权。很NB,也很累。内存声明维护释放都靠自己。一不小心内存垃圾就会占据大量资源,Bug也多。
Java把内存控制权交给了Java虚拟机。开发人员不用刻意去匹配释放内存。但如果不知道Java虚拟机内存管理机制,发生内存异常后,排查问题就会很难。


虚拟机运行时数据区域

根据《Java虚拟机规范(Java SE 7版)》Java管理的内存将会分为以下几个内存区域:Java内存管理—虚拟机运行时数据区域_第1张图片

  • 程序计数器:随线程建立而创建(每个线程都有自己独立的程序计数器,且相互独立,下称线程私有)。可以看作当前线程运行字节码的行号指示器,它记录了虚拟机字节码地址(Java方法中)。在Native方法(Java调用的非Java代码接口)中,其为null。
    程序计数器是Java虚拟机中唯一一个没有任何OutOfMemoryError 情况的内存区域。

  • Java虚拟机栈:随线程建立而创建(线程私有)。描述Java方法执行的内存模型。每个方法创建时都会创建一个栈帧,用于存储局部变量表,操作数,动态链接,方法出口等信息。每个方法从调用到完成,对应栈帧在Java虚拟机栈中从入栈到出栈的过程。

    • 如果线程申请的栈深度大于虚拟机能提供的栈深,会抛出StackOverFlowError异常
    • 如果线程请求动态扩展无法申请到足够的内存,会抛出OutOfMemoryError异常
  • 本地方法栈:与虚拟机栈作用完全相同。只不过虚拟机栈服务于Java方法,而本地方法栈服务于Native方法。异常抛出原因与种类与Java虚拟机栈相同

  • Java堆: 在虚拟机启动时创建(线程共享)。用于存放对象实例。也是Java垃圾收集管理的主要区域(所以也称为GC堆——GarbageCollected-Heap,即垃圾堆)。Java堆在物理上(内存中)不连续,逻辑上连续。

    • 在对象实例在Java堆中也无法容下,抛出OutOfMemoryError异常
  • 方法区:线程共享。用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。
    • 方法区无法满足内存分配需求时,抛出OutOfMemoryError异常
  • 直接内存:并不是Java虚拟机运行时数据区域的一部分,是由NIO类提供的一种基于通道和缓冲区的I/O方式通过Native方法直接分配的堆外内存。开发者通过DirectByteBuffer对象对这块区域引用操作。其大小受物理内存大小限制

    • 物理内存无法满足内存分配需求时,抛出OutOfMemoryError异常


参考书籍《深度理解Java虚拟机:JVM高级特性与最佳实践 第二版》

你可能感兴趣的:(Java语言理解)