Java 运行时数据区域

Java运行时内存区域

Java 运行时数据区域_第1张图片

程序计数器

程序计数器是当前线程所执行的字节码的行号指示器

为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器。所以程序计数器是线程私有的内存。

虚拟机栈

虚拟机栈是由栈帧组成的,每个方法在执行的同时都会创建一个栈帧用于存储局部变量表操作数栈动态链接方法出口等信息。

每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机中入栈到出栈的过程。

虚拟机栈也是线程私有的。

该区域可能出现的异常情况:

  • 如果线程请求的栈深度大于虚拟机所允许的栈深度,将抛出StackOverflowError异常。
  • 如果虚拟机栈可以动态扩展,但在扩展时无法申请到足够的内存,将抛出OutOfMemoryError异常。

本地方法栈

本地方法栈与虚拟机栈发挥的作用相似,区别是虚拟机栈执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Natvie方法服务。

Java堆

Java堆是Java虚拟机所管理的最大内存区域,几乎所有的对象实例都在这里分配内存。可利用参数 -Xms 和 -Xmx 进行堆内存控制。

这块区域也是垃圾收集器管理的主要区域,由于收集器基本都采用分代收集算法,所有堆内存也分为新生代、老年代,再细致一点的有Eden空间、Fron Survivor空间、To Survivor空间等。

Java堆是线程共享的内存区域。

方法区(JDK 1.7)

方法区用于存储已经被虚拟机加载的类信息,常量、静态变量编译后的代码等数据。这块区域也被称为永久代。
可利用参数 -XX:PermSize -XX:MaxPermSize 控制初始化方法区和最大方法区大小。

方法区是线程共享的内存区域。

元空间(JDK 1.8)

在 JDK1.8 中已经移除了方法区(永久代),并使用了一个元空间进行代替,使用本地内存来存放类的元数据

默认情况下元空间会根据使用情况动态调整,避免了由于加载类过多从而出现 java.lang.OutOfMemoryError: PermGen。

可使用-XX:MaxMetaspaceSize来控制最大内存。

和永久代不同的是,元空间存储类的元信息,静态变量和常量池等并入堆中。相当于永久代的数据被分到了堆和元空间中。

运行时常量池

在JDK1.7中,运行时常量池是方法区的一部分,除了保存Class文件中的类的版本、字段、方法接口等描述信息外,还有常量池,用于存放编译器生成的各种字面量和符号引用外,还会把翻译出来的直接引用也存储在运行时常量池中。

直接内存

直接内存也称为堆外内存,并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中农定义的内存区域。

在JDK1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O 方式,它可以使用native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。

本机直接内存的分配不会受到Java堆大小的限制,受到本机总内存大小限制。
配置虚拟机参数时,不要忽略直接内存,防止出现OutOfMemoryError异常。

你可能感兴趣的:(JVM)