Java 可视化垃圾回收_动力节点Java学院整理

发布时间 - 2026-01-11 01:14:56    点击率:

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

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

基础

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

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

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

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

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

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

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

图一

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

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

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

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

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

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

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<size>—— 设置预留给堆的最小内存值 -Xmx<size>—— 设置预留给堆的最大内存值 -XX:MaxPermSize=<size>——设置永久代的最大内存值

——有利于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日志!——原始日志文件难以阅读——使用工具
  • 使用工具来帮助自己调优——测量,而不是猜测

以上所述是小编给大家介绍的Java 可视化垃圾回收,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


# java  # 可视化垃圾回收  # java垃圾收集器与内存分配策略详解  # 浅谈Java内存区域划分和内存分配策略  # Java内存分配多种情况的用法解析  # Java分代垃圾回收策略原理详解  # 解析Java内存分配和回收策略以及MinorGC、MajorGC、FullGC  # 这是  # 应用程序  # 是一个  # 是在  # 递归  # 是有  # 就会  # 都有  # 内存管理  # 两条  # 它在  # 它不  # 小编  # 自己的  # 的人  # 都是  # 而不是  # 加载  # 汇编程序  # 这一 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 湖南网站制作公司,湖南上善若水科技有限公司做什么的?  如何在Windows 2008云服务器安全搭建网站?  公司网站制作需要多少钱,找人做公司网站需要多少钱?  怎么用AI帮你为初创公司进行市场定位分析?  浅谈Javascript中的Label语句  详解vue.js组件化开发实践  Laravel Eloquent模型如何创建_Laravel ORM基础之Model创建与使用教程  Laravel Vite是做什么的_Laravel前端资源打包工具Vite配置与使用  无锡营销型网站制作公司,无锡网选车牌流程?  Swift中switch语句区间和元组模式匹配  Laravel中间件如何使用_Laravel自定义中间件实现权限控制  javascript中的try catch异常捕获机制用法分析  智能起名网站制作软件有哪些,制作logo的软件?  Laravel Sail是什么_基于Docker的Laravel本地开发环境Sail入门  如何做网站制作流程,*游戏网站怎么搭建?  如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南  阿里云高弹*务器配置方案|支持分布式架构与多节点部署  Laravel如何使用Sanctum进行API认证?(SPA实战)  北京网站制作费用多少,建立一个公司网站的费用.有哪些部分,分别要多少钱?  如何挑选最适合建站的高性能VPS主机?  html5的keygen标签为什么废弃_替代方案说明【解答】  Laravel怎么在Controller之外的地方验证数据  如何正确下载安装西数主机建站助手?  Midjourney怎样加参数调细节_Midjourney参数调整技巧【指南】  如何用PHP工具快速搭建高效网站?  Laravel请求验证怎么写_Laravel Validator自定义表单验证规则教程  Laravel如何使用Socialite实现第三方登录?(微信/GitHub示例)  如何选择PHP开源工具快速搭建网站?  详解Oracle修改字段类型方法总结  Laravel如何使用Eloquent ORM进行数据库操作?(CRUD示例)  如何彻底删除建站之星生成的Banner?  如何在七牛云存储上搭建网站并设置自定义域名?  焦点电影公司作品,电影焦点结局是什么?  Laravel如何实现API资源集合?(Resource Collection教程)  uc浏览器二维码扫描入口_uc浏览器扫码功能使用地址  javascript中数组(Array)对象和字符串(String)对象的常用方法总结  韩国代理服务器如何选?解析IP设置技巧与跨境访问优化指南  Win11怎么关闭专注助手 Win11关闭免打扰模式设置【操作】  Laravel辅助函数有哪些_Laravel Helpers常用助手函数大全  Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理  手机怎么制作网站教程步骤,手机怎么做自己的网页链接?  悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤  LinuxCD持续部署教程_自动发布与回滚机制  Laravel如何使用Seeder填充数据_Laravel模型工厂Factory批量生成测试数据【方法】  济南网站建设制作公司,室内设计网站一般都有哪些功能?  百度输入法全感官ai怎么关 百度输入法全感官皮肤关闭  JS碰撞运动实现方法详解  Laravel怎么创建自己的包(Package)_Laravel扩展包开发入门到发布  Laravel storage目录权限问题_Laravel文件写入权限设置  Laravel如何实现模型的全局作用域?(Global Scope示例)