JVM——内存模型

1、程序计数器(Program Counter):

用于记录当前线程待执行的字节码指令位置 。若执行的是Native方法则计数器值为null 。是唯一一个不会触发OOM 的区域,生命周期与线程相同

  • 函数调用:当前PC值压入栈 ,PC更新为函数入口地址返回时函数地址弹出到PC地址
  • 循环/条件分支:直接跳转到对应的字节码指令位置
  • 多线程切换:涉及到各个线程PC的保存和恢复

2、虚拟机栈:

线程独享内存 ,每个方法在执行时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息 ,可能会抛出StackOverflowError(栈过深,超出栈容量)和OOM异常。生命周期与线程相同

3、本地方法栈:

与虚拟机栈类似 ,但是为Native方法准备的栈,在HotSpot虚拟机中和虚拟机栈合二为一。也可能发生栈过深异常或OOM异常

4、堆(Heap):

JVM中最大的内存区域,被所有线程共享用于存放对象实例。 在虚拟机启动时创建,被划分为新生代和老年代,利于GC新生代又被分为Eden区和Survivor区。堆溢出时也会发生OOM异常。

5、方法区(元空间):

使用本地内存用于存储已被虚拟机加载的类信息、常量、静态变量、方法字节码、符号引用等数据。被称为堆的逻辑部分,可以不选择垃圾回收。内存不足抛出OOM异常。

  • 运行时常量池:方法区的一部分,用于存放编译期或运行时生成的各种字面量和符号引用。内存不足抛出OOM异常,jdk1.8后移入本地内存中的元数据区域,jdk1.7前位于堆内的永久代

6、直接内存:

不属于JVM运行时数据区的一部分,通过NIO类引入,是一种堆外内存,可显著提高IO性能。受本机总内存的限制。内存不足抛出OOM异常。

栈详解:

  • 栈中存储的是当前线程中的局部变量、操作数栈和方法调用信息,方法返回地址及以一些临时数据
  • 栈中一般存储的是对象的引用,指向堆中的对象实例
  • 每当有方法调用时都会创建一个栈帧,用于存储该方法的信息,方法执行完毕后对应栈帧也会移除
  • 栈的存取速度比堆快,使用的是简单的先进后出结构
  • 栈空间相对较小且固定,可能会发生栈溢出(递归过深或内存超限)
  • 栈中数据对于线程来说是私有的

堆详解:

  • 存储对象实例 ,数据的生命周期交由GC管理
  • 存储空间较大 ,但存取速度相对较慢
  • 所有线程共享数据

新生代:

分为Eden区Survivor区Eden区用于存放存活概率较低的对象 (如大多数新创建的对象),Eden区相对较小 ;Survivor区分为from区和to区 ,每次进行Minor GC后,Eden区存活的对象和form区存活的对象会移动到to区域,并增加它们的年龄。

Eden区满时 ,会触发Minor GC,将存活对象复制到幸存区或老年代,清空Eden区和from区

老年代:

存放长期存活的对象 ,存储空间一般是新生代的两倍 ,因此Major GC的发生频率较低

老年代空间不足(阈值默认45%)时 ,会触发对应回收器的回收(默认G1回收器),并发回收失败则触发full GC

大对象区:

某些回收器实现(如G1垃圾收集器),为大对象分配了专门的区域。大对象区域指需要大量连续空间的对象,例如大数组 。这类对象直接分配在老年代 ,以避免新生代频繁复制导致长时间STW

内存泄漏:

本质上是已经不再需要使用的对象仍然存在引用无法被回收导致可用内存逐渐减少

常见原因:
  • 静态集合使用静态数据结构 (HashMap或ArrayList),静态对象生命周期与JVM进程相同,存储对象且未在使用完后及时清理
  • 事件监听:未取消事件对事件源的监听,导致对象持续被引用
  • 会话或连接未及时关闭:例如数据库连接,流式处理的连接都会分配内存进行处理,若没有关闭也会造成内存泄漏。
  • 线程数据未释放 :未停止的线程持有对无用对象的引用 (例如ThreadLocal实例内部持有value的强引用,而key由于弱引用已被回收
相关推荐
皮皮林5513 小时前
SpringBoot 加载外部 Jar,实现功能按需扩展!
java·spring boot
rocksun3 小时前
认识Embabel:一个使用Java构建AI Agent的框架
java·人工智能
Java中文社群4 小时前
AI实战:一键生成数字人视频!
java·人工智能·后端
王中阳Go5 小时前
从超市收银到航空调度:贪心算法如何破解生活中的最优决策谜题?
java·后端·算法
shepherd1115 小时前
谈谈TransmittableThreadLocal实现原理和在日志收集记录系统上下文实战应用
java·后端·开源
维基框架5 小时前
Spring Boot 项目整合Spring Security 进行身份验证
java·架构
日月星辰Ace6 小时前
Java JVM 垃圾回收器(四):现代垃圾回收器 之 Shenandoah GC
java·jvm
天天摸鱼的java工程师7 小时前
商品详情页 QPS 达 10 万,如何设计缓存架构降低数据库压力?
java·后端·面试
天天摸鱼的java工程师7 小时前
设计一个分布式 ID 生成器,要求全局唯一、趋势递增、支持每秒 10 万次生成,如何实现?
java·后端·面试
阿杆7 小时前
一个看似普通的定时任务,如何优雅地毁掉整台服务器
java·后端·代码规范