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

一. 运行时数据区域

1.1 程序计数器

用于存储线程正在执行的指令的行数,执行普通方法时存储字节码文件地址,执行本地方法时为空。

1.2 Java虚拟机栈

有一个局部变量表,存储byte, short, int, long, boolean, char, float, double八种基本数据类型和引用指针。

1.3 本地方法栈

与Java虚拟机栈功能类似,区别在于Java虚拟机栈为虚拟机运行java方法时服务,而本地方法栈为虚拟机运行本地方法时服务。

1.4 Java堆

所有的对象实例以及数组都应当在堆上分配。
各个线程共享的内存区域。

1.5 方法区

各个线程共享的内存区域(与堆一样)
用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

方法区:
https://blog.csdn.net/duoyu779553/article/details/105878755/

有存放方法信息、类型信息和域信息等。

1.6 运行时常量池

运行时常量池是方法区的一部分。

String.intern():
当调用intern方法时,如果池已经包含与equals(Object)方法确定的相当于此String对象的字符串,则返回来自池的字符串。
否则,此String对象将添加到池中,并返回对此String对象的引用。

final类变量的值在编译期间就被确定了,因此保存在类的常量池里面,然后在加载类的时候,复制进方法区的运行时常量池里面,final类变量存储在运行时常量池里面,每一个使用它的类保存着一个对其的引用。

1.7 直接内存

不是虚拟机运行时数据区的一部分,也不是《java虚拟机规范》中定义的内存区域。

操作系统设备管理DMA相关
内存不需要经过CPU直接与外围设备交换数据

二. HotSpot虚拟机对象

2.1 对象的创建

划分可用空间:

  1. 指针碰撞
  2. 空闲列表

线程安全:

  1. CAS配上失败重试的方法保证更新操作的原子性
  2. 本地线程分配缓冲(TLAB)

2.2 对象的内存布局

  1. 对象头
  2. 实例数据
  3. 对齐数据

2.3 对象的访问定位

  1. 句柄访问
  2. 直接指针访问

三. OOM异常

除程序计数器外,虚拟机栈、本地方法栈、Java堆、方法区都会发生OOM,不是《java虚拟机规范》定义的直接内存也会。
虚拟机栈和本地方法栈还会发生StackOverFlowError。

3.1 Java堆溢出

java.lang.OutOfMemoryError: Java heap space

判断是内存泄漏还是内存溢出

  1. 内存泄漏:堆中对象已死亡但无法回收
    查找泄漏对象到GC Roots的引用链。
  2. 内存溢出:堆中对象确实存活
    检查Java虚拟机的堆参数设置、从代码上检查是否存在某些对象生命周期过长、持有状态时间过长、存储结构设计不合理等。

3.2 虚拟机栈和本地方法区溢出

3.3 方法区和运行时常量池溢出

3.4 本机直接内存溢出

参考文献: 深入理解Java虚拟机 第3版 周志明著

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值