JVM的内存分区

Posted luojiahu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM的内存分区相关的知识,希望对你有一定的参考价值。

JVM的内存分区

这篇文章尝试讨论清楚JVM的内存分区情况。

1.       JVM的内存和系统内存的关系

下图是对系统内存及JVM内存的大致描绘

 

对大多数操作系统,内存可以分为物理内存RAM及Swap(交换区)两大部分,Swap Space在物理上是一块独立的磁盘区域,当操作系统发现内存不够使用时,便开始使用交换区。

在系统层面,Linux系统的内存大致可以划分为:

  1. BIN,内核引导内存
  2. Kernel Space(内核内存),操作系统进行程序调度,内存分配,硬件资源管理等动作需要的内存
  3. User Space(用户内存),提供给各个进程使用

一个JAVA程序开始运行之后,是存在于系统之上的一个进程。这个进程所占用的内存由JVM管理。

2.       JVM内存的划分

JVM的内存可以划分为以下几个主要部分:

 

  1. Program Counter Register,程序计数器,线程私有,是一块较小的内存空间,可以理解为当前线程执行字节码的行号指示器。
  2. Method Area,方法区,由各线程共享,用于加载类信息,常量,静态变量等数据。在HotSpot虚拟机的实现中,称这部分内存为Permanent Generation(永久代),这使得虚拟机可以像管理堆内存一样对这部分内存进行管理,可以通过参数-XX:MaxPermSize指定永久代的上限。而在其他虚拟机实现中并未使用永久代来实现方法区。当方法区无法满足内存分配需要时,便会抛出OutOfMemoryError。
  3. Java Heap,堆,线程共享,对大部分应用来说,这是JVM种最大的一块内存区域。JVM规范规定:所有的对象实例和数组都要在堆上分配。

堆是内存回收的主战场,因此由称为Garbage Collected Heap(GC堆),在分代收集策略下,堆可以进一步划分为新生代和老年代,更细致的:

  • Eden区,对象第一次创建时,从Eden区开辟空间
  • Survivor区,当Eden区不足以进行下次内存分配时,JVM触发一次GC,经过GC但未被回收的对象,被转移到Survivor区。Survivor分为From,To两部分,多次内存回收时未被回收的对象在这两块区域中来回转移。
  • Old区,当经过一定次数的GC后仍未被回收的对象,JVM将其转移到老年代区

  4. JVM Stack,JAVA虚拟机栈,线程私有,其生命周期与对应的线程相同。当每个方法执行时,均会创建一个栈帧(Stack Frame)用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每个方法的执行和完成,便对应着Stack Frame在虚拟机栈中的出栈和入栈的过程。通常意义上粗糙地将JVM内存划分为堆和栈,其中的栈便指的是JVM Stack.

  5. Native Method Stack,本地方法栈,与JVM Stack类似,本地方法栈对应的是Native方法的执行管理。

此外,程序运行所需要的内存开辟在JVM的内存空间中,也可以直接申请系统内存(Directive Memory),但是直接申请的系统内存不受JVM的垃圾回收管理,其释放由系统层面控制,因此对于不关注内存回收的JAVA程序员来说,容易导致内存溢出等问题的发生。

以上是关于JVM的内存分区的主要内容,如果未能解决你的问题,请参考以下文章

JVM内存分区

JVM中的内存分区简介

JVM内存分区和各分区溢出测试

JVM内存分区和各分区溢出测试

JVM内存分区

jvm内存分区及各区线程问题