大咖直播-鸿蒙原生开发与智能提效实战!>>> 了解详情
写点什么

可视化 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:388906
用户头像

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

关注

评论

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

Python应用之基础结构-链表-合并两个有序链表

芯动大师

链表 10月月更 合并有序

Vue常用修饰符大全

CoderBin

面试 Vue 前端 10月月更

LinkedList源码分析(二)

知识浅谈

linkedlist 10月月更

跟着卷卷龙一起学Camera--金字塔融合法02

卷卷龙

ISP camera 10月月更

hashmap常见面试题

普罗米修斯

10月月更

斐波那契数

掘金安东尼

算法 10月月更

Spring Boot「01」构建 REST API

Samson

Java Spring Boot Web 学习笔记 10月月更

IDEA的Docker插件实战(Dockerfile篇)

程序员欣宸

Docker IDEA 10月月更

【C语言内功修炼】动态内存管理的奥秘

Albert Edison

C语言 malloc 动态内存 10月月更 free

Qt | 实现自定义手机号输入框控件

YOLO.

qt 10月月更 C++

跟着卷卷龙一起学Camera--ISO

卷卷龙

ISP camera 10月月更

Python应用之基础结构:链表- 删除排序链表中的重复元素

芯动大师

10月月更 链表结构 基本元素

业务流程巡检拨测常用的开源工具

阿泽🧸

10月月更 业务流程

数据结构线性表链表

IC00

c 链表 数据结构算法 10月月更 链表结构

Photoshop软件应用项目(二)

张立梵

设计师 ps 10月月更

2022-10-08:以下go语言代码输出什么?A、0 0;B、0 4;C:4 0;D:4 4。 package main const s = “Go101.org“ // len(s) == 9

福大大架构师每日一题

golang 福大大 选择题

Python应用之基础结构:二叉树 前序遍历

芯动大师

二叉树 遍历 10月月更

40道Promise输出题,你都会了吗?🔥

CoderBin

面试 前端 JavaScrip 10月月更

【算法作业】实验二:给立方体排序的小明&&同时整除的数

清风莫追

数据结构 算法 10月月更

Python进阶(五)浅谈python匿名函数及编写无参数decorator

No Silver Bullet

Python 10月月更 匿名函数 无参数decorator

C++ | 关于extern关键字的使用

YOLO.

qt 10月月更 C++

AI大模型的白垩纪

脑极体

分布式定时任务设计及其框架

穿过生命散发芬芳

10月月更 分布式定时任务

大数据ELK(十八):Beats 简单介绍和FileBeat工作原理

Lansonli

10月月更 大数据ELK

MFC|CCombobox控件修改编辑框光标显示位置

中国好公民st

c c++ 10月月更

10项任务助你落地架构课程!

华仔

架构实战营

2022 年适用于 Linux 和 Windows 的五款最佳 Python 代码编辑器

wljslmz

Python ide 编辑器 10月月更

【Java深入学习】可见性

Geek_65222d

10月月更

【算法作业】实验三:划分集合-贪心 & 可能的IP地址-回溯

清风莫追

数据结构 算法 10月月更

【算法作业】实验四:逆波兰表达式求值 & Fibonacci数列的尾递归与非递归程序

清风莫追

数据结构 算法 10月月更

Python进阶(七)浅谈python3和Python2的区别

No Silver Bullet

Python3 区别 10月月更 Python2

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