java内存管理--内存区域和内存溢出

本文详细介绍了Java虚拟机(JVM)的内存管理机制,包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区等功能区域的作用及特点。此外,还深入探讨了对象创建的过程以及对象在内存中的布局。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而一直存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。根据《Java虚拟机规范》的规定,Java虚拟机所管理的内存将会包括以下几个运行时数据区域,如图所示。

在这里插入图片描述

运行时数据区

程序计数器

一个较小的内存空间
当前线程所执行的字节码的行号指示器
线程私有

Java虚拟机栈

线程私有,生命周期与线程相同
存储局部变量表,操作数栈,动态连接,方法等信息
局部变量表的存储空间一局部变量槽表示

本地方法栈

与Java虚拟机栈类似,区别在于服务对象的不同,服务本地方法
对本地方法栈中方法所使用的语言,数据结构无强制要求

Java堆

虚拟机所管理的内存中最大的一块
所有线程共享,在虚拟机启动时创建
唯一的目的时存放对象实例,“几乎”所有的对象都是在这里分配内存的
是垃圾管理器管理的内存区域
线程共享的Java堆可以分配出多个线程私有的分配缓冲区
Java堆可以存储在物理上不连续的内存上,但是逻辑上连续

方法区

各线程共享,用于存储已被虚拟机加载的类型信息,常量,静态变量等

运行时常量池

方法区的一部分,用于存放编译期生成的各种字面量和符号引用

直接内存

将本地Naative函数库直接存储到堆外内存

HotSpot虚拟机 内存管理

对象创建

(1)检查new指令的参数是否能在常量池中定位到一个类的引用符号,并检查该符号引用代表的类是否已被加载、解析和初始化
(2)分配内存,内存的大小在类加载完成后便可以完全确认,内存分配实际就是从Java堆中划分出一块确定大小的内存,分配方式有两种
{指针碰撞:java内存规整,一边是已使用,一边是未使用的,直接移动指针空闲列表:Java内存不规整,维护一个列表记录哪些以用/未用\begin{cases} 指针碰撞:java内存规整,一边是已使用,一边是未使用的,直接移动指针\\ 空闲列表:Java内存不规整,维护一个列表记录哪些以用/未用 \end{cases}{java使使Java/
java内存规整与否有垃圾收集器是否带有空间压缩整理能力决定
内存分配并不是线程安全的,解决方式有两种
{分配内存空间动作同步本地线程分配缓冲(TLAB)\begin{cases} 分配内存空间动作同步\\ 本地线程分配缓冲(TLAB) \end{cases}{线TLAB
(3)分配内存空间初始化,将分配空间(不包括对象头)初始化为零值
(4)对象设置,将对视时那个类的实例,GC分代等信息添加到对象头
(5)构造函数

对象的内存布局

对象在堆内存中的存储布局可以划分为三个部分
(1)对象头header:存储两类信息,一类为对象自身的运行式数据,哈希码,GC等;一类是类型指针,对象指向它的类型的元数据的指针
(2)实例数据:对象真正存储的有效信息
(2)对齐填充:占位符,使得对象的大小为8字节的整数倍

对象的访问定位

Java程序会通过栈上的reference数据量操作堆上的具体对象,也有两种操作方式
(1)句柄访问:Java堆中划分出一块内存来作为句柄池,存储对象的句柄池句柄中宝航对象的实例数据和类型数据
(2)直接访问:reference中存储的是对象地址
句柄访问存储稳定,直接访问会减少访问开销

常见内存溢出

java堆溢出
虚拟机栈和本地方法栈溢出
方法区和运行时常量池溢出
本机直接内存溢出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值