最近在看点 JVM 的东西,看到 JVM 的内存区域就做了点笔记。
运行时数据区域
先来看看虚拟机的内存区域的基本组成吧。
JDK1.8 之前:
JDK1.8 以后:
其中,内存区域主要分为线程私有和线程共享。
线程私有:
- 程序计数器
- 虚拟机栈
- 本地方法栈
线程共享:
- 堆(heap)
- 方法区
- 直接内存(非运行时数据区域的一部分)
程序计数器
程序计数器在虚拟机中占用内存较小,相当于当前线程在执行字节码文件的行号指示器,类似于调试时语句的执行步骤。
注 程序计数器是虚拟机中唯一一个不会出现 OutOfMemoryError
的内存区域,它的生命周期和线程一样,随线程的创建而创建,消亡而消亡。
虚拟机栈
通常我们说的栈内存,指的就是虚拟机栈(或者说当中的局部变量部分)
它描述的是 Java 方法执行的内存模型,每次方法调用的数据都是通过栈传递的。
虚拟机栈是由一个个栈帧组成的,每个栈帧都拥有一个局部变量表(存放基本类型和对象引用)、操作数栈、动态链、方法出口信息。
虚拟机栈的生命周期和线程相同,会出现 OutOfMemoryError
和 StackOverFlowError
两种异常。
-
OutOfMemoryError
:若虚拟机栈的内存大小不允许扩展,当线程请求栈的深度超过当前虚拟机栈的最大深度时,则抛出该异常。 -
StackOverFlowError
:若虚拟机的内存大小运行动态扩展,且当线程请求栈时内存刚好用完了,无法再进行动态扩展,这时就会抛出该异常。
本地方法栈
与虚拟机栈相似,不同的是:
-
虚拟机栈是为虚拟机执行 Java 方法(字节码)服务的
-
本地方法栈是为虚拟机使用到的 Native 方法(虚拟机底层的方法,C 语言编写,可以访问操作系统底层信息)服务的
本地方法栈同样会有栈帧,其存放的东西与虚拟机栈相同(面向的是本地方法),在 HotSpot 虚拟机(Sun JDK 和 OpenJDK 中所带的虚拟机)实现中是把本地方法栈和虚拟机栈合二为一的
也会出现 OutOfMemoryError
和 StackOverFlowError
两种异常。
堆(heap)
堆作为线程共享的区域,在虚拟机中占用的内存是最大的,它的生命周期和虚拟机相同,随着虚拟机的启动而创建,用于存放对象实例和数组内存,是垃圾收集器管理的主要区域。
方法区
方法区是用于存储已被虚拟机加载过的类信息、常量、静态变量、即时编译器编译后的代码等数据。
运行时常量池
用于存放编译期生成的各种字面量和符号引用。
其作为方法区的一部分,自然会受到方法区内存的限制,当常量池无法再申请到内存是便会抛出 OutOfMemoryError
异常。
直接内存
直接内存并不属于虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用。而且也可能导致 OutOfMemoryError 异常出现。
以上就是看完资料后做的一些笔记,鉴于原文后面的东西我现在也看不太懂,便不做记录,日后能力提升了再做记录吧。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于