在Java里什么是垃圾回收机制_JavaGC基础原理解析
发布时间 - 2026-02-01 00:00:00 点击率:次Java GC通过可达性分析(从GC Roots出发)判断对象是否为垃圾,而非引用计数;新生代用复制算法(因对象存活率低),老年代用标记-整理(因对象存活率高);GC由内存压力触发(如Eden满、老年代不足),非System.gc()强制执行。
Java里的垃圾回收(GC)机制,本质是JVM自动识别并回收堆中“不再可达”的对象所占内存的过程——它不靠引用计数,而靠从GC Roots出发的可达性分析;不是随时运行,而是按分代策略在Eden区满、老年代空间不足等时机触发。
怎么判断一个对象是不是“垃圾”?别信引用计数,看GC Roots能不能摸到它
很多人以为“没被变量引用了就是垃圾”,但Java不用引用计数法,因为循环引用(比如A.instance = B且B.instance = A)会让计数器永远不为0,导致内存泄漏。JVM实际用的是可达性分析:从一组固定的起点(GC Roots)出发,沿着引用链往下找。找不到路径的对象,才被标记为可回收。
常见的GC Roots包括:
-
虚拟机栈中正在执行的方法的局部变量(比如MyObject obj = new MyObject()里的obj) - 类的
static字段(如public static MyObject CACHE) - 方法区中的常量(如字符串常量池里的
"hello") -
本地方法栈中JNI调用持有的对象
注意:被标记为不可达 ≠ 立刻被回收。如果对象重写了finalize()(已弃用),还可能被“复活”一次——但这属于历史包袱,现代代码应完全避免依赖它。
立即学习“Java免费学习笔记(深入)”;
为什么新生代用复制算法,老年代却用标记-整理?因为对象“活下来”的概率差十倍以上
这不是拍脑袋定的,而是基于“弱代假设”:98%的新对象活不过一次Minor GC。所以新生代(Eden + S0 + S1)用复制算法——只把活着的少量对象拷过去,清空原区域,快且无碎片。但老年代里对象平均存活几十次GC,复制成本太高,改用标记-整理,边清理边压缩,避免大对象分配失败。
典型配置与行为:
-
-XX:SurvivorRatio=8→ Eden : S0 : S1 = 8:1:1,意味着每次Minor GC后,最多约10%的存活对象能进入Survivor区 - 对象在Survivor区“熬过”一定次数(默认15次,由
-XX:MaxTenuringThreshold控制)就晋升到老年代 - 大对象(如超过
-XX:PretenureSizeThreshold的数组)会直接进老年代,跳过新生代——避免在复制过程中反复搬运
什么时候会触发GC?别迷信System.gc(),它只是个礼貌的请求
System.gc()不会立刻触发Full GC,甚至可能被JVM完全忽略(尤其在启用了-XX:+DisableExplicitGC时)。真实触发条件更依赖内存压力:
- Minor GC:当
Eden区满时必然发生,扫描新生代,存活对象移入Survivor或老年代 - Full GC:通常由老年代空间不足引发,但也可能因元空间(
Metaspace)耗尽、CMS并发失败、或显式调用System.gc()(未禁用时)触发 - 特别注意:频繁Minor GC但晋升很少,可能是
Survivor空间太小或MaxTenuringThreshold设得太低,导致对象“早熟”进老年代,埋下Full GC隐患
怎么看GC是否出问题?先加-XX:+PrintGCDetails -XX:+PrintGCTimeStamps,再盯住三件事
光看日志不够,得抓关键信号:
- Minor GC频率突增(比如从每5分钟1次变成每10秒1次)→ 检查是否有短生命周期对象暴增(如循环内new HashMap)
- 每次Minor GC后老年代使用率持续上升 → 对象晋升过多,可能是Survivor区溢出或对象本身生命周期变长
- Full GC耗时超过200ms或频繁发生 → 很可能有内存泄漏,用
jstat -gc确认YGC/FGC次数与耗时,再用jmap -histo或堆转储分析大对象来源
真正容易被忽略的点是:GC日志里显示“Allocation Failure”并不等于代码写错了,它只是说明Eden撑不住了——但背后到底是业务流量上涨、缓存没设上限,还是某个工具类偷偷持有了静态引用,得结合堆快照才能定位。别只盯着算法名字,要盯住你自己的对象怎么活、怎么死、又

# java
# js
# cms
# 虚拟机
# 工具
# 栈
# ai
# 字符串常量
# 为什么
# jvm
# Static
# 常量
# 局部变量
# 字符串
# 循环
# 堆
# public
# 并发
# 对象
# 算法
# 可达
# 它只
# 自己的
# 的是
# 是个
# 最多
# 什么时候
# 找不到
# 很多人
# 住了
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
郑州企业网站制作公司,郑州招聘网站有哪些?
Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理
如何在浏览器中启用Flash_2025年继续使用Flash Player的方法【过时】
Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制
电视网站制作tvbox接口,云海电视怎样自定义添加电视源?
绝密ChatGPT指令:手把手教你生成HR无法拒绝的求职信
php增删改查怎么学_零基础入门php数据库操作必知基础【教程】
北京专业网站制作设计师招聘,北京白云观官方网站?
Linux系统运维自动化项目教程_Ansible批量管理实战
php读取心率传感器数据怎么弄_php获取max30100的心率值【指南】
高防服务器租用指南:配置选择与快速部署攻略
如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南
Laravel模型事件有哪些_Laravel Model Event生命周期详解
如何获取上海专业网站定制建站电话?
如何快速搭建高效WAP手机网站?
如何在云虚拟主机上快速搭建个人网站?
如何快速登录WAP自助建站平台?
微信小程序 HTTPS报错整理常见问题及解决方案
Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践
北京网站制作公司哪家好一点,北京租房网站有哪些?
laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法
JavaScript如何实现路由_前端路由原理是什么
大学网站设计制作软件有哪些,如何将网站制作成自己app?
Laravel如何使用Laravel Vite编译前端_Laravel10以上版本前端静态资源管理【教程】
Python文本处理实践_日志清洗解析【指导】
Laravel中间件如何使用_Laravel自定义中间件实现权限控制
网站制作软件免费下载安装,有哪些免费下载的软件网站?
制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?
Laravel如何使用Blade组件和插槽?(Component代码示例)
javascript中数组(Array)对象和字符串(String)对象的常用方法总结
laravel怎么配置和使用PHP-FPM来优化性能_laravel PHP-FPM配置与性能优化方法
Laravel怎么实现观察者模式Observer_Laravel模型事件监听与解耦开发【指南】
Python企业级消息系统教程_KafkaRabbitMQ高并发应用
如何在七牛云存储上搭建网站并设置自定义域名?
用v-html解决Vue.js渲染中html标签不被解析的问题
php在windows下怎么调试_phpwindows环境调试操作说明【操作】
Laravel中的withCount方法怎么高效统计关联模型数量
高防服务器租用如何选择配置与防御等级?
浅谈javascript alert和confirm的美化
Laravel如何实现URL美化Slug功能_Laravel使用eloquent-sluggable生成别名【方法】
jQuery中的100个技巧汇总
微信小程序 scroll-view组件实现列表页实例代码
详解Android——蓝牙技术 带你实现终端间数据传输
LinuxCD持续部署教程_自动发布与回滚机制
如何在IIS中新建站点并配置端口与物理路径?
七夕网站制作视频,七夕大促活动怎么报名?
Laravel如何使用Socialite实现第三方登录?(微信/GitHub示例)
猪八戒网站制作视频,开发一个猪八戒网站,大约需要多少?或者自己请程序员,需要什么程序员,多少程序员能完成?
百度输入法全感官ai怎么关 百度输入法全感官皮肤关闭
高配服务器限时抢购:企业级配置与回收服务一站式优惠方案

