首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JVM揭秘之旅:打破性能瓶的终极指南(6)

JVM揭秘之旅:打破性能瓶的终极指南(6)

作者头像
半旧518
发布2025-07-30 08:42:09
发布2025-07-30 08:42:09
1180
举报
文章被收录于专栏:半旧的技术栈半旧的技术栈

专栏简介 「为什么Java程序员必须啃透JVM?」 JVM是Java生态的“灵魂引擎”,但多数开发者仅停留在API调用层面。当面临频发GC卡顿、诡异OOM崩溃或线程死锁顽疾时,是否曾因底层原理的模糊而束手无策?本专栏将带您穿透技术迷雾,系统攻克JVM核心领域:

⚙️ 硬核原理拆解:从字节码执行、类加载双亲委派,到G1/ZGC回收器设计,逐层剖析JVM的运作机制; 🛠️ 调优实战手册:结合大厂案例,详解参数配置(如-XX:+HeapDumpOnOutOfMemoryError)、内存泄漏定位(MAT工具)、并发瓶颈破解; 🚀 前沿技术追踪:涵盖元空间、JIT编译、协程(Loom项目)等新特性,提前掌握未来技术栈; 💡 面试高频攻略:深度解析京东/华为等大厂JVM面试题(如“CMS与G1的权衡”“内存屏障作用”)6,8。 适合读者: ✅ 渴求突破CRUD的Java工程师 ✅ 被性能问题困扰的架构师 ✅ 备战P7/P8级技术面试的求职者

专栏承诺:不用空洞理论堆砌,每篇均附可复现的代码案例及调优脚本。跟随专栏,您将获得从“被动救火”到“主动防御”的JVM掌控力!

1、垃圾回收算法

标记清除

很简单,分为两个步骤,标记和清除。

image-20250708221756799
image-20250708221756799

注意,这里只是逻辑清除。在某个位置记录这些被“清除”的地址,在需要使用时分配这些地址空间即可。

优点:速度快,你只要记录地址,没有真的清除数据。

缺点:内存都是碎片。造成空间不连续。

标记整理

也很简单,看下图就好。

image-20250708222955605
image-20250708222955605

优点:没有内存碎片。

缺点:时间较长。

复制算法

image-20250708223757744
image-20250708223757744
image-20250708223343717
image-20250708223343717
image-20250708223501792
image-20250708223501792

优点:不会产生内存碎片

缺点:占用双倍的内存空间

2、分代垃圾回收

分代回收机制

实际jvm并不会只采用一种算法,而是结合使用三种算法。

整个jvm内存被划分为下面几块。

image-20250708224020235
image-20250708224020235

我们来详细分析下,分代回收机制是怎么工作的。第一次垃圾回收。

image-20250708224705249
image-20250708224705249

标记、复制。存活对象寿命数字+1

image-20250708224839821
image-20250708224839821

交换From、To位置。

image-20250708224948210
image-20250708224948210

第二次垃圾回收。

image-20250708225239534
image-20250708225239534

依旧是标记、复制。

image-20250708230408238
image-20250708230408238

回收垃圾对象,放入垃圾回收前没放进去新对象,交换from区域和to区域。

image-20250708230505146
image-20250708230505146

当幸存区中对象经过一个寿命阈值(比如是15),还没有被回收。会将其晋升到老年代中。

image-20250708230734063
image-20250708230734063

如果新生代、老年代都快满了,怎么办?

当然是触发一次彻底的GC,我们称之为Full GC。

image-20250708230946290
image-20250708230946290

总结下。

image-20250728181205013
image-20250728181205013

相关VM参数

我们接下来用代码来解读下垃圾回收的过程,在这之前,我们先了解相关VM参数。

image-20250728181840686
image-20250728181840686

GC分析

接下来,开始用代码分析分代回收过程。

我们看下面栗子。光溜溜的一个类。

image-20250728182715499
image-20250728182715499

运行打印信息如下。

image-20250728183405425
image-20250728183405425

接下来创建7M对象。

image-20250728184417309
image-20250728184417309

接下来放入512KB对象。重新运行。

image-20250728184649007
image-20250728184649007

再放512KB对象。

image-20250728184916253
image-20250728184916253

GC分析:大对象oom

如果直接创建一个大对象,会怎么样?

看下面栗子。

image-20250728185141918
image-20250728185141918

这时,新生代空间肯定不够,直接放到了老年代。

image-20250728185252903
image-20250728185252903

如果放2个8M对象呢?新生代和老年代都放不下了,会oom

image-20250728185504502
image-20250728185504502

接下来,再给大家介绍一个误区。

如果我们的代码是运行在一个线程。这个线程运行时OOM会不会影响主线程,让主线程结束?

image-20250728185821401
image-20250728185821401

运行结果如下。

image-20250728185912247
image-20250728185912247

不过,我们的程序这个时候还没有结束。主线程也并没有意外结束。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-07-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、垃圾回收算法
    • 标记清除
    • 标记整理
    • 复制算法
  • 2、分代垃圾回收
    • 分代回收机制
    • 相关VM参数
    • GC分析
    • GC分析:大对象oom
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档