最近在看点JVM的东西,看到JVM的内存区域就做了点笔记。

运行时数据区域

先来看看虚拟机的内存区域的基本组成吧。

JDK1.8之前:

JVM运行时数据区域.png
JVM运行时数据区域.png

JDK1.8以后:

20193Java运行时数据区域JDK1.8.png
20193Java运行时数据区域JDK1.8.png

其中,内存区域主要分为线程私有和线程共享。

线程私有:

  • 程序计数器
  • 虚拟机栈
  • 本地方法栈

线程共享:

  • 堆(heap)
  • 方法区
  • 直接内存(非运行时数据区域的一部分)

程序计数器

程序计数器在虚拟机中占用内存较小,相当于当前线程在执行字节码文件的行号指示器,类似于调试时语句的执行步骤。

程序计数器是虚拟机中唯一一个不会出现OutOfMemoryError的内存区域,它的生命周期和线程一样,随线程的创建而创建,消亡而消亡。

虚拟机栈

通常我们说的栈内存,指的就是虚拟机栈(或者说当中的局部变量部分)

它描述的是Java方法执行的内存模型,每次方法调用的数据都是通过栈传递的。

虚拟机栈是由一个个栈帧组成的,每个栈帧都拥有一个局部变量表(存放基本类型和对象引用)、操作数栈、动态链、方法出口信息。

虚拟机栈的生命周期和线程相同,会出现OutOfMemoryErrorStackOverFlowError两种异常。

  • OutOfMemoryError:若虚拟机栈的内存大小不允许扩展,当线程请求栈的深度超过当前虚拟机栈的最大深度时,则抛出该异常。

  • StackOverFlowError:若虚拟机的内存大小运行动态扩展,且当线程请求栈时内存刚好用完了,无法再进行动态扩展,这时就会抛出该异常。

本地方法栈

与虚拟机栈相似,不同的是:

  • 虚拟机栈是为虚拟机执行Java方法(字节码)服务的

  • 本地方法栈是为虚拟机使用到的Native方法(虚拟机底层的方法,C语言编写,可以访问操作系统底层信息)服务的

本地方法栈同样会有栈帧,其存放的东西与虚拟机栈相同(面向的是本地方法),在HotSpot虚拟机(Sun JDK和OpenJDK中所带的虚拟机)实现中是把本地方法栈和虚拟机栈合二为一的

也会出现OutOfMemoryErrorStackOverFlowError两种异常。

堆(heap)

堆作为线程共享的区域,在虚拟机中占用的内存是最大的,它的生命周期和虚拟机相同,随着虚拟机的启动而创建,用于存放对象实例和数组内存,是垃圾收集器管理的主要区域。

方法区

方法区是用于存储已被虚拟机加载过的类信息、常量、静态变量、即时编译器编译后的代码等数据。

运行时常量池

用于存放编译期生成的各种字面量和符号引用。

26038433.jpg
26038433.jpg

其作为方法区的一部分,自然会受到方法区内存的限制,当常量池无法再申请到内存是便会抛出OutOfMemoryError异常。

直接内存

直接内存并不属于虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用。而且也可能导致OutOfMemoryError异常出现。

以上就是看完资料后做的一些笔记,鉴于原文后面的东西我现在也看不太懂,便不做记录,日后能力提升了再做记录吧。

评论