JVM自动内存管理——java内存区域与内存溢出异常

1概述

对于java来说,在虚拟机自动内存管理机制的帮助下,不需要为每个操作写配对的delete/free代码,不过,一但出现内存泄漏和溢出方面的问题,如果不了解虚拟机是怎么使用内存,那么排查问题将会十分困难。

2运行时数据区域

2.1程序计数器

程序计数器是一块比较小的内存区域,可以看成当前线程执行字节码的行号指示器。

由于jvm的多线程是通过线程轮换,分配处理器的执行时间来实现的,为了线程切换后能回到正确的执行位置,每条线程都需要应该独立的程序计数器,个线程程序计数器间不受影响。

如果线程正在执行一个Java方法,那么计数器记录的是虚拟机字节码的地址,如果执行的是本地方法,则为空。

此内存区域是唯一一个没有规定任何OutOfMemoryError情况的区域

2.2 java虚拟机栈

java虚拟机栈也是线程私有的,它的生命周期和线程相同。虚拟机栈描述的是java执行的线程内存模型:每个方法被执行时,jvm会同步创建一个栈帧用于存储局部变量表,操作数栈等信息,方法从调用到执行完毕的过程,对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

这个区域定义了两种异常状况:

如果线程请求的栈深度大于虚拟机允许的深度,抛出StackOverflowError异常;

如果虚拟机栈容量可以动态扩展,当扩展无法申请足够内存时会抛出OutOfMemoryError异常。

2.3 本地方法栈

与虚拟机栈相似,只是一个是java方法,一个是本地方法。

2.4 java堆

对于java应用程序来说,java堆是虚拟机管理的内存中最大的一块。被所有线程共享。在虚拟机启动时创建,唯一目的是存放对象实例。

java堆是垃圾收集器管理的区域,java堆主流的是可扩展的,从分配内存角度,java堆可以分出多个线程私有的分配缓冲区,细分只是为了更好地回收内存,如果堆没有内存可以分配且无法扩展,jvm抛出OutOfMemoryError异常。

2.5方法区

是线程共享的内存区域,方法区可以不选择垃圾收集,所以方法区的内存回收很难令人满意。方法区无法满足内存需求时,也会抛出OutOfMemoryError异常。

2.6运行时常量池

是方法区的一部分,用来放编译后的字面量和符号引用。

2.7 直接内存

直接内存不是运行时数据区的一部分,jdk1.4中加的NIO,可以使用native函数库直接分配堆外内存,然后通过存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。

虽然不受java堆大小限制,但仍然会受本机总内存限制。

相关推荐
z落落12 分钟前
C# 泛型方法(原理、类型推断、多泛型参数)+泛型效率(普通类型 VS Object装箱 VS 泛型)
开发语言·c#
L_090714 分钟前
【C++】异常
开发语言·c++
世辰辰辰1 小时前
批量修改图片/文本名子
开发语言·python·批量修改文件名
郑洁文1 小时前
基于Spring Boot的流浪动物救助网站
java·spring boot·后端·毕设·流浪动物救助
J-Tony112 小时前
【JVM】编译&&解释
jvm
螺丝钉code2 小时前
JAVA项目 Claude code CLAUDE.md 到底应该怎么写
java·人工智能·claude code
z落落3 小时前
C# 四种特殊类:抽象类、密封类、静态类、部分类
开发语言·c#
摇滚侠3 小时前
Maven 入门+高深 单一架构案例 54-59
java·架构·maven·intellij-idea
VidDown4 小时前
Webhook 调试器:让第三方回调“原形毕露”
java·开发语言·javascript·编辑器·postman
折哥的程序人生 · 物流技术专研4 小时前
Java 23 种设计模式:从踩坑到精通 | 原型模式 —— 克隆对象,深拷贝与浅拷贝的坑你踩过吗?
java·设计模式·架构·原型模式·单一职责原则