当前位置: 首页 > news >正文

JVM 核心概念深度解析

最近正在复习Java八股,所以会将一些热门的八股问题,结合ai与自身理解写成博客便于记忆
在这里插入图片描述

一、JVM内存结构/运行时数据区

JVM运行时数据区主要分为以下几个部分:

  1. 程序计数器(PC Register)

    • 线程私有,记录当前线程执行的字节码行号
    • 唯一不会出现OOM的内存区域
  2. Java虚拟机栈(VM Stack)

    • 线程私有,存储栈帧(局部变量表、操作数栈、动态链接、方法出口等)
    • 可能出现StackOverflowError和OutOfMemoryError
  3. 本地方法栈(Native Method Stack)

    • 线程私有,为Native方法服务
    • 同样可能出现StackOverflowError和OutOfMemoryError
  4. Java堆(Heap)

    • 线程共享,存放对象实例和数组
    • GC主要工作区域,分新生代(Eden、Survivor)和老年代
    • 可能出现OutOfMemoryError
  5. 方法区(Method Area)

    • 线程共享,存储类信息、常量、静态变量等
    • JDK 8后由元空间(Metaspace)实现,使用本地内存
    • 可能出现OutOfMemoryError
  6. 运行时常量池

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

二、对象分配与逃逸分析

创建对象不一定分配在堆里,JVM会通过以下技术优化对象分配:

  1. 逃逸分析(Escape Analysis)

    • 分析对象作用域是否逃逸出方法或线程
    • 未逃逸对象可进行栈上分配或标量替换
  2. 栈上分配(Stack Allocation)

    • 将未逃逸对象分配在栈上,随栈帧出栈自动销毁
    • 减少GC压力
  3. 标量替换(Scalar Replacement)

    • 将未逃逸对象拆解为基本类型变量
    • 完全避免对象分配
  4. TLAB(Thread Local Allocation Buffer)

    • 每个线程在Eden区私有的分配区域
    • 避免多线程竞争指针碰撞
    • 默认大小为Eden区的1%

三、垃圾回收机制

根可达性算法

  • 从GC Roots出发,标记所有可达对象
  • GC Roots包括
    • 虚拟机栈中引用的对象
    • 方法区中类静态属性引用的对象
    • 方法区中常量引用的对象
    • 本地方法栈中JNI引用的对象
    • 同步锁持有的对象
    • JMXBean等系统对象

三色标记法

  • 白色:未被访问的对象
  • 灰色:已被访问但引用未扫描完的对象
  • 黑色:已被访问且引用已扫描完的对象
  • 作用:并发标记时追踪对象状态
  • 好处:支持并发标记,减少STW时间

漏标问题解决方案

  1. 增量更新(Incremental Update)

    • CMS采用,记录新增引用关系
    • 写屏障(Write Barrier)实现
  2. 原始快照(Snapshot At The Beginning, SATB)

    • G1采用,记录删除的引用关系
    • 写屏障实现

浮动垃圾问题

  • 产生原因:并发清理阶段用户线程产生的新垃圾
  • 解决方案
    • 下次GC时清理
    • CMS通过预留空间(-XX:CMSInitiatingOccupancyFraction)避免并发失败

四、垃圾收集器详解

CMS(Concurrent Mark Sweep)

设计目标与特点

  • 目标:最小化老年代收集的停顿时间
  • 类型:老年代收集器(与ParNew配合使用)
  • 算法:标记-清除(Mark-Sweep)算法
  • 工作模式:并发收集(与用户线程并行)

详细工作流程

  1. 初始标记(Initial Mark) - STW

    • 暂停所有应用线程(STW)
    • 标记GC Roots直接关联的对象
    • 时间极短(通常1-10ms)
  2. 并发标记(Concurrent Mark)

    • 与用户线程并发执行
    • 从GC Roots开始遍历整个对象图
    • 时间较长但不需要STW
  3. 重新标记(Remark) - STW

    • 再次暂停所有应用线程
    • 处理并发标记期间的对象变化
    • 使用增量更新算法解决漏标问题
    • 比初始标记时间长但远短于并发标记
  4. 并发清除(Concurrent Sweep)

    • 与用户线程并发执行
    • 清理未被标记的垃圾对象
    • 使用空闲列表(free-list)管理内存

G1(Garbage First)

  • 特点
    • 分Region的内存布局
    • 可预测的停顿模型(-XX:MaxGCPauseMillis)
    • 混合回收(Young GC + Mixed GC)

详细工作流程

  1. Young GC

    • STW操作
    • 回收所有Eden和Survivor区
    • 存活对象复制到新的Survivor或晋升到Old区
  2. 并发标记周期

    • 初始标记(Initial Mark):STW,与Young GC同步进行
    • 根区域扫描(Root Region Scan):扫描Survivor区引用
    • 并发标记(Concurrent Mark):全堆对象标记
    • 最终标记(Final Mark):STW,处理SATB缓冲区
    • 清理(Cleanup):统计各Region存活对象
  3. Mixed GC

    • 回收部分Young和Old Region
    • 基于停顿预测模型选择收益最高的Region
    • 通过-XX:MaxGCPauseMillis控制目标停顿时间
  • 四个阶段

    1. 初始标记(STW)
    2. 并发标记
    3. 最终标记(STW)
    4. 筛选回收(STW)
  • 优点:高吞吐兼顾低延迟,适合大堆

  • 缺点:内存占用较高

五、类加载机制

双亲委派模型

  • 加载流程

    1. 子加载器先委托父加载器加载
    2. 父加载器无法完成时子加载器尝试加载
  • 好处

    • 避免类重复加载
    • 保证核心类安全(如java.lang.Object)
    • 实现类的层次化隔离

破坏双亲委派

  • 方式

    1. SPI机制(如JDBC):使用线程上下文类加载器
    2. OSGi:网状类加载模型
    3. 热部署:自定义类加载器
  • Tomcat的实现

    1. Web应用类优先自行加载
    2. 共享类库由Common类加载器加载
    3. 不同Web应用隔离(JSP类使用独立加载器)

六、JVM调优经验

  1. 内存调优

    • -Xms/-Xmx:堆初始/最大大小(建议设为相同值)
    • -Xmn:新生代大小(建议占堆1/3到1/2)
    • -XX:MetaspaceSize/-XX:MaxMetaspaceSize:元空间大小
  2. GC调优

    • -XX:+UseG1GC:启用G1收集器
    • -XX:MaxGCPauseMillis=200:目标停顿时间
    • -XX:InitiatingHeapOccupancyPercent=45:G1触发并发周期阈值
  3. 监控工具

    • jstat:GC统计
    • jmap:堆内存分析
    • jstack:线程分析
    • VisualVM/JProfiler:图形化分析
  4. 常见问题处理

    • OOM:分析堆/栈/元空间dump
    • CPU高:定位热点线程/方法
    • 长时间GC:调整收集器或内存比例
http://www.xdnf.cn/news/879751.html

相关文章:

  • CB/T 3361-2019 甲板敷料检测
  • 中小企业IT运维痛点与OMS主动运维体系解析
  • 装一台水冷主机
  • uniappx插件nutpi-idcard 开发与使用指南(适配鸿蒙)
  • Linux C学习路线全概及知识点笔记2(仅供个人参考)
  • uniapp实现的简约美观的星级评分组件
  • uniapp图片文档预览
  • PHP 8.5 即将发布:管道操作符、强力调试
  • springboot mysql/mariadb迁移成oceanbase
  • 基于Java(SpringBoot、Mybatis、SpringMvc)+MySQL实现(Web)小二结账系统
  • 【图片识别改名】如何批量将图片按图片上文字重命名?自动批量识别图片文字并命名,基于图片文字内容改名,WPF和京东ocr识别的解决方案
  • 【SSM】SpringMVC学习笔记7:前后端数据传输协议和异常处理
  • 阿里云事件总线 EventBridge 正式商业化,构建智能化时代的企业级云上事件枢纽
  • 【Spark征服之路-2.2-安装部署Spark(二)】
  • 力扣LeetBook数组和字符串--二维数组
  • 【无标题】路径着色问题的革命性重构:拓扑色动力学模型下的超越与升华
  • 网络测试实战:金融数据传输的生死时速
  • C++学习-入门到精通【14】标准库算法
  • C++11实现TCP网络通讯服务端处理逻辑简化版
  • ARM处理器工作模式
  • MCP通信方式之Streamable HTTP
  • ZooKeeper 安装教程(Windows + Linux 双平台)
  • Redis 安装配置和性能优化
  • 【bug】Error: /undefinedfilename in (/tmp/ocrmypdf.io.9xfn1e3b/origin.pdf)
  • 仓库拉下ssm项目配置启动
  • Java 高频面试题场景(四):社区老年大学在线学习平台系统
  • Android四大组件通讯指南:Kotlin版组件茶话会
  • 新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
  • 6.5本日总结
  • 【设计模式】门面/外观模式