50万奖金+官方证书,深圳国际金融科技大赛正式启动,点击报名 了解详情
写点什么

可视化 Java 垃圾回收

  • 2014-02-26
  • 本文字数:2601 字

    阅读完需:约 9 分钟

垃圾回收,就像双陆棋一样,只需几分钟来学习,但要用一生来精通。

Ben Evans 是一名资深培训师兼顾问,他在演讲可视化垃圾回收中从基础谈起讨论了垃圾回收。

以下是对其演讲的简短总结。

基础

当谈到释放不再使用的内存,垃圾回收已经在很大程度上取代了早期技术,比如手动内存管理和引用计数。

这是件好事,因为内存管理令人厌烦,学究式地簿记是计算机擅长的,而不是人擅长的。在这方面,语言的运行时环境比人强。

现代的垃圾回收非常高效,远远超过早期语言中典型的手工分配。通常,具有其它语言背景的人只盯着垃圾回收造成的中断,却没有完全理解自动内存管理发生作用的上下文环境。

标记 & 清除是 Java(及其它运行时环境)用于垃圾回收的基本算法。

在标记 & 清除算法中,引用会从每个线程栈的桢指向程序的堆。所以,从栈开始,循着指针找到所有可能的引用,然后再循着这些引用递归下去。

当递归完成,就找到了所有的活对象,其它的都是垃圾。

请注意,人们经常漏掉的一点是,运行时环境本身也有一个“分配清单(allocation list)”,上面列出了指向每个对象的指针,该列表由垃圾回收器负责维护,并帮助垃圾回收器进行垃圾清理。因此,运行时环境总是可以找出由它创建但尚未回收的对象。

图一

上面插图中所示的栈只是一个与单个应用程序线程相关的栈;每个应用程序线程都有一个类似的栈,每个栈本身都有一组指向堆的指针。

如果垃圾回收器试图在应用程序运行过程中获取活对象的快照,那么它就要追踪运动着的目标,那样很容易漏掉一些严重超时的对象分配,因而无法获得一个准确的快照。因此,“Stop the World”是有必要的;也就是,停止应用程序线程足够长的时间,以便捕获活对象的快照。

下面是垃圾回收器必须遵循的两条黄金法则:

  1. 垃圾回收器必须回收所有的垃圾。
  2. 垃圾回收器必须从不回收任何活对象。

但这两条规则并不是对等的;如果违反了第二条规则,结果会使数据遭到破坏。

另一方面,如果违反了第一条规则,则会是另一种情况,系统并不总是能够回收所有的垃圾,但最终会回收所有的垃圾,那么这是可以接受的,而实际上,这是垃圾回收器的基本原理。

HotSpot

现在,我们来说下 HotSpot,它实际上是一个 C、C++ 以及许多特定于平台的汇编程序组成的混合体。

当人们想到解释器,就会想到一个很大的 while 循环,其中包含一个很长的 switch 语句。但 HotSpot 解释器比那个要复杂的多(由于性能原因)。在开始阅读 JDK 源代码的时候,就会发现 HotSpot 中实在是有许多汇编程序代码。

对象创建

Java 会预先分配大量的连续空间,就是我们所说的“堆”。之后,HotSpot 完全在用户空间里管理这块内存。

如果一个 Java 进程占用了大量的系统(或内核)时间,那么毫无疑问,它不是在进行垃圾回收——因为所有的垃圾回收内存“簿记(bookkeeping)”都是在用户空间进行的。

内存池

图二

“永久代(PermGen)”是一个存储区域,用于保存那些需要在程序生存期内一直存活的东西,如类的元数据。不过,随着应用程序服务器的出现,它们有自己的类加载器,并且需要重新加载类的元数据,永久代作为一个优化决策开始显得糟糕,所幸,它在 Java 8 中消失了。

Java 8 将会使用一个名为“元空间(Metaspace)”的新概念。元空间与永久代并不完全相同。它在堆的外面,由操作系统管理。这意味着,它不会在 Java 堆中,而是在本地内存里。目前,这还不是一个非常好的消息,因为没有多少工具能够让用户轻松地查看本地内存。所以,永久代消失是件好事,但工具赶上这个变化还需要一些时间。

Java 堆布局

现在,我们来看下 Java 堆。注意堆空间之间的虚拟空间。它们提供了一点浮动量,以允许对内存池进行一定量的尺寸调整,又不用为任何对象移动付出代价。

图三

“弱代假设(Weak Generational Hypothesis)”

就现状而言,究竟为什么要将堆分成所有这些内存池?

图四

有的运行时事实无法通过静态分析推导出来。上面的插图说明有两组对象:一组存活时间短,一组存活时间长——所以,做额外的簿记以便利用这一事实是有意义的。在 Java 平台中,有许多类似的作为优化写入平台的事实。

演示

Ben Evans 进行了一系列的动画演示。第一个演示是个 Flash,说明了对象在 Eden 区和一个新生代 Survivor 空间之间移动,并最终进入老年代的过程。

图五是用 JavaFX 再现了同样的过程。

图五

运行时开关

‘强制性’参数

  • -verbose:gc——为用户输出一些 GC 信息
  • -Xloggc:< 文件路径 >——指定日志输出路径,要确保磁盘有空间
  • -XX:+PringGCDetails——为辅助工具提供“最低限度信息(Minimum information)” ——用这个参数代替 -verbose:gc
  • –XX:PrintTenuringDistribution——“过早提升(Premature promotion)”信息

基本堆大小参数

  • -Xms —— 设置预留给堆的最小内存值
  • -Xmx —— 设置预留给堆的最大内存值
  • -XX:MaxPermSize=——设置永久代的最大内存值 ——有利于 Spring 应用程序和应用服务器

以前,我们被教导要把 -Xms 和 -Xmx 的值设的一样大。不过这已经变了。因此,现在可以为 -Xms 设置一个合理范围内较小的值,或者根本就不设置,因为堆的适应能力现在已经非常好了。

其它参数

  • -XX:NewRatio=N
  • -XX:NewSize=N
  • -XX:MaxNewSize=N
  • -XX:MaxHeapFreeRatio
  • -XX:MinHeapFreeRatio
  • -XX:SurvivorRatio=N
  • -XX:MaxTenuringThreshold=N

图六

为什么要有日志文件

日志文件的好处是能够用于取证分析,可以使用户免于为了再现问题而不得不再执行一次代码(如果是一个罕见的生产环境错误,那么重现并不容易)。

另外,它们包含的信息比针对内存的 JMX MXBeans 所能提供的信息更多,且不说轮询 JMX 本身会引入一系列 GC 问题。

工具

  • HP JMeter(用 Google 查询一下)——免费,非常可靠,但不再提供支持 / 功能增强
  • GCViewer ——免费,开源,但界面有点丑
  • GarbageCat ——名字最好听
  • IBM GCMV ——支持 J9
  • jClarity Censum ——界面最美观,而且最有用——不过,这是我们的偏见!

小结

  • 需要了解一些 GC 基础理论
  • 要让新生代的大部分对象在年轻时死亡
  • 打开 GC 日志!——原始日志文件难以阅读——使用工具
  • 使用工具来帮助自己调优——测量,而不是猜测

查看完整演讲视频,请点击这里

关于作者

Ben Evans是一家 Java/JVM 性能分析创业公司 jClarity 的 CEO。在业余时间,他是伦敦 Java 社区的一名负责人,也是 Java 社区过程执行委员会成员之一。他先前的项目包括:对 Google IPO、金融交易系统做性能测试,为若干 90 年代最大的电影开发获奖网站等等。

查看英文原文:**** Visualizing Java Garbage Collection

2014-02-26 06:388899
用户头像

发布了 256 篇内容, 共 99.3 次阅读, 收获喜欢 12 次。

关注

评论

发布
暂无评论
发现更多内容

传帮带 人才梯队建设经验总结(15)

万里无云万里天

人才培养 工业 工厂运维

常用Web 实时通信技术:原理+选型,一篇通关

京东科技开发者

哈尔滨 2025 等保测评实操:流程规范与企业核心应对策略

等保测评

Kingbase与ETL:如何实现金融级数据库的安全数据同步

谷云科技RestCloud

数据处理 数据同步 ETL KingBase 数据集成平台

C#线性查找算法

追逐时光者

C#

GPT-4o 新增说话人分割模型 Transcribe-Diarize;巨人网络开源方言模型 DiaMoE-TTS 丨日报

声网

云栖实录 | 实时计算 Flink 全新升级 - 全栈流处理平台助力实时智能

阿里云大数据AI技术

flink 阿里云 AI 实时计算 Fluss

跨区域协同,破局AI落地痛点!「AI共创 三生万物」司马阅2025企业AI落地应用峰会苏州站完美收官

司马阅

ESP32 + MCP over MQTT:通过大模型控制智能硬件设备

EMQ映云科技

大会回顾:不止于 “智能”!详解Data+AI 如何赋能企业决策与效率升级

袋鼠云数栈

数据治理 发布会 Data + AI 袋鼠云 数据筑基

AWS CloudTrail 可观测最佳实践

观测云

aws cloudtrail

不仅仅是代码助手:用 Plugins 将 Claude Code 打造成你的专属工具链 - 概念篇(1/4)

Robin Min

LLM plugins vibe coding Claude-Code Coding Agent

解决 Nginx 路径前缀问题:从 /serviceA 到 /special/serviceA 的平滑迁移

玄兴梦影

nginx 代理 nginx反向代理 Nginx 代理

JDD Oxygen智能零售论坛 | 《大模型时代的广告营销变革与实践》

京东科技开发者

本地盘的价格,云磁盘的弹性:百度智能云弹性临时盘来了

Baidu AICLOUD

块存储 #云存储 云磁盘

C#/.NET/.NET Core技术前沿周刊 | 第 59 期(2025年10.20-10.26)

追逐时光者

C# .net

压缩指针:64位系统下,Java虚拟机是如何“偷”回4字节内存的?

poemyang

Java虚拟机 java对象

PDF/epub一键转思维导图,AI帮你10分钟搞定全书精华

阿星AI工作室

产品 AI 工具 电子书

技术实践:在基于 RISC-V 的 ESP32 上运行 MQTT over QUIC

EMQ映云科技

橱窗用LED显示屏,店铺“亮”起来

Dylan

品牌 LED LED display LED显示屏 LED屏幕

研发排查问题的利器:一款方法调用栈跟踪工具

京东科技开发者

怎样通过Abaqus代理商思茂信息采购软件?-Abaqus采购流程

思茂信息

仿真 几何图形 abaqus

企业选择IM即时通讯软件,为何更注重私有化部署?

BeeWorks

即时通讯 IM 私有化部署

【第三期】USM上海线下工作坊

ShineScrum

敏捷活动

Apache RocketMQ × AI:面向 Multi-Agent 的事件驱动架构

阿里巴巴云原生

阿里云 云原生 Apache RocketMQ

AI赋能“一带一路”:司马阅入选《“一带一路”人工智能应用场景案例集(2025)》

司马阅

告别“信息孤岛”,BeeWorks 如何为制造业数智化转型搭好“底座”?

BeeWorks

即时通讯 IM 私有化部署

2025 哈尔滨等保测评指南:标准调整与落地执行方向

等保测评

发布会回顾|袋鼠云发布多模态数据中台,重构AI时代的数据底座

袋鼠云数栈

数据中台 发布会 多模态数据 袋鼠云 数栈

可视化Java垃圾回收_Java_Ben Evans_InfoQ精选文章