JAVA内存区域与内存溢出异常

本文详细介绍了Java虚拟机(JVM)中的主要内存区域,包括线程私有的Java虚拟机栈及其异常处理机制,所有线程共享的Java堆、方法区及常量池的功能与作用。此外还探讨了对象创建过程中内存分配的两种方式——指针碰撞与空闲列表,并解释了对象在内存中的布局以及访问方式。

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

@(Android)


  • 与程序计数器一样,Java虚拟机栈也是线程私有的,它的生命周期与线程相同。

    栈用于存储局部变量(包括基本类型和对象引用),操作数栈动态链接方法出口等信息

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

    1. 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverError异常
    2. 如果虚拟机栈可以动态扩展部分的Java虚拟机都可以动态扩展

Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域唯一目的就是存放对象的实例,几乎所有的对象实例都在这里分配存放

方法区

方法区与java堆一样,是哥哥线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。

常量池

常量池是方法区的一部分

用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放

HotSpot虚拟机对象探秘

对象的创建

指针碰撞

假设java堆中内存是绝对完整的,所有用过的内存都放在一边,空闲的内存放在另一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲空间挪动一段与对象大小相等的距离

空闲列表

如果java堆中的内存并不是完整的,已使用的内存和空闲的内存相互交错,那就没办法简单地进行指针碰撞了,虚拟机就必须维护一个列表,记录下哪些内存是可用的,在分配的时候从列表中找到一块足够大的空间划分给对象实例,并更新列表上的记录

对象的内存分配

对象在内存中存储的布局可分为3块区域:对象头实例数据对齐填充

对象的访问定位

目前主流的访问方式有使用句柄指针两种

使用句柄访问的话,那么java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息

  • 内存溢出:是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
  • 内存泄露:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值