JVM之java内存区域异常的相关说明
下文是笔者收集的Java内存区域异常的相关简介说明,如下所示:
Java语言是运行在JVM虚拟机上的语言,它由JVM管理内存,下文笔者讲述由JVM产生的异常简介说明
将内存分为多个不同的数据区域进行管理
这些内存区域具有不同的作用、不同创建和销毁时间
有的区域是在JVM进程启动时分配
有的区域则与用户线程(程序本身的线程)的生命周期相关
这些都是由JVM规范所规定,JVM分为以下几个运行时数据区域:
随线程启动而创建、线程销毁而销毁
虚拟机栈描述的java方法执行的内存模型
每个方法在执行开始会创建一个栈帧(Stack Frame),
用于存储局部变量表、操作数栈,动态链接、方法出口等
每个方法的调用执行和返回结束,都对应有一个栈帧在虚拟机栈入栈和出栈的过程
虚拟机栈作用几乎是一样的
虚拟机栈是为java方法执行提供出入栈服务,而本地方法栈则是为虚拟机执行Native方法提供服务
可认为是线程执行字节码的行号指示器(指向一条指令),
java执行时通过改变计数器的值来获的下一条需要执行的指令,分支、循环、跳转、异常处理、线程恢复等执行顺序都要依赖这个计数器来完成
虚拟机的多线程是通过轮流切换并分配处理器执行时间实现,
处理器(对多核处理器来说是一个内核)在一个时刻只能在执行一条命令
因此线程执行切换后需要恢复到正确的执行位置,每个线程都有一个独立的程序计算器
在虚拟机启动时创建
存储已经被虚拟机加载的类型信息、常量、静态变量、即时编译期编译后的代码等数据;
虚拟机规范对于方法区的实现没有过多限制,和堆内存一样不需要连续的物理内存空间,
大小可以固定或者可扩展,还可以选择不实现垃圾回收;
当方法区无法满足内存分配需求时将会抛出OutOfMemoryError异常
但这部分内存可能被频繁用到
在java程序使用到Native方法时(如 NIO),
可能会直接在堆外分配内存
但是内存总空间大小是有限的,
也会遇到内存不足的情况,一样会抛出OutOfMemoryError异常
Java语言是运行在JVM虚拟机上的语言,它由JVM管理内存,下文笔者讲述由JVM产生的异常简介说明
JVM中内存区域分布
JVM运行java程序时将内存分为多个不同的数据区域进行管理
这些内存区域具有不同的作用、不同创建和销毁时间
有的区域是在JVM进程启动时分配
有的区域则与用户线程(程序本身的线程)的生命周期相关
这些都是由JVM规范所规定,JVM分为以下几个运行时数据区域:
虚拟机栈
虚拟机栈内存区域是线程私有的,随线程启动而创建、线程销毁而销毁
虚拟机栈描述的java方法执行的内存模型
每个方法在执行开始会创建一个栈帧(Stack Frame),
用于存储局部变量表、操作数栈,动态链接、方法出口等
每个方法的调用执行和返回结束,都对应有一个栈帧在虚拟机栈入栈和出栈的过程
局部变量表: 用于存储局部变量,存储8种基本数据类型,引用类型的地址 局部变量的内存空间,在编译器可完成分配,在方法运行期间无需修改局部变量表大小 ----------------------------------------------------------------------------------------- 此处可能会发生2种异常: 1.当线程请求的栈深度大于虚拟机所允许的深度(?),将抛出StackOverflowError异常 2.当虚拟机可以动态扩展,当扩展是无法申请到足够内存,将抛出OutOfMemory异常
本地方法栈
本地方法栈内存区域是是线程私有虚拟机栈作用几乎是一样的
虚拟机栈是为java方法执行提供出入栈服务,而本地方法栈则是为虚拟机执行Native方法提供服务
在虚拟机规范中,对本地方法栈实现方式没有强制规定, 可以由具体虚拟机自由实现; HotSpot虚拟机是直接把虚拟机栈和本地方法栈合二为一实现; --------------------------------------------------------------------------- 与虚拟机栈一样,本地方法栈同样会抛出StackOverflowError和OutOfMemory异常。
程序计算器
程序器计算器是线程私有的内存区域可认为是线程执行字节码的行号指示器(指向一条指令),
java执行时通过改变计数器的值来获的下一条需要执行的指令,分支、循环、跳转、异常处理、线程恢复等执行顺序都要依赖这个计数器来完成
虚拟机的多线程是通过轮流切换并分配处理器执行时间实现,
处理器(对多核处理器来说是一个内核)在一个时刻只能在执行一条命令
因此线程执行切换后需要恢复到正确的执行位置,每个线程都有一个独立的程序计算器
当执行一个java方法时,这个程序计算器记录(指向)当前线程正在执行的字节码指令地址, 如果正在执行的是Native方法,这个计算器的值为undefined, 这是因为HotSpot虚拟机线程模型是原生线程模型,即每个java线程直接映射OS(操作系统)的线程,执行Native方法时,由OS直接执行,虚拟机的这个计数器的值是无用的; 由于这个计算器是一块占用空间很小的内存区域,为线程私有,不需要扩展, 是虚拟机规范中唯一一个没有规定任何OutOfMemoryError异常的区域。
堆内存(Heap)
java堆是线程共享的内存区域,是虚拟机管理的内存最大的一块区域在虚拟机启动时创建
java堆内存: 主要是存储对象实例,几乎所有的对象实例(包括数组)都是存储在这里 这也是垃圾回收(GC)最主要的内存区域 --------------------------------------------------------------------- 根据JVM虚拟机规范,java堆内存可以处于不连续的物理内存中 但是要在逻辑上是连续的,并且空间扩展也没有限制, 既可以是固定大小,也可以是棵扩展的 当堆内存没有足够的空间完成实例分配,而且也无法扩展时,将会抛出OutOfMemoryError异常
方法区
方法区和堆内存一样,是线程共享的内存区域;存储已经被虚拟机加载的类型信息、常量、静态变量、即时编译期编译后的代码等数据;
虚拟机规范对于方法区的实现没有过多限制,和堆内存一样不需要连续的物理内存空间,
大小可以固定或者可扩展,还可以选择不实现垃圾回收;
当方法区无法满足内存分配需求时将会抛出OutOfMemoryError异常
直接内存
直接内存不是JVM虚拟机管理内存的一部分但这部分内存可能被频繁用到
在java程序使用到Native方法时(如 NIO),
可能会直接在堆外分配内存
但是内存总空间大小是有限的,
也会遇到内存不足的情况,一样会抛出OutOfMemoryError异常
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。