Java 可视化垃圾回收_动力节点Java学院整理
作者:mrr 发布时间:2023-02-19 07:03:55
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 可视化垃圾回收网站的支持!


猜你喜欢
- 现在很多Android应用在首次安装完都会有指引如何使用该应用的某些功能的指引界面,这样会获得很好的用户体验,能够帮助用户更好使用应用的某些
- 查看代码执行mybatis的sql语句File–>Settings–>Plugins 搜索 MyBatis Log Plugin
- 在我们平时写程序的时候,有些参数是经常改变的,而这种改变不是我们预知的。比如说我们开发了一个操作数据库的模块,在开发的时候我们连接本地的数据
- 一、直接执行SQL查询:1、mappers文件节选<resultMap id="AcModelResultMap"
- 在上面的例子中多次使用到了Thread类的join方法。我想大家可能已经猜出来join方法的功能是什么了。对,join方法的功能就是使异步执
- 最近使用到了maven的profile功能,发现这个功能的确很好用也很实用,这块的知识比较多也比较乱,其实真正理解了之后非常简单,为了巩固总
- 一、采用Object.toString()toString方法是java.lang.Object对象的一个public方法。在java中任何
- 一、类加载流程类加载的流程可以简单分为三步:加载连接初始化而其中的连接又可以细分为三步:验证准备解析下面会分别对各个流程进行介绍。1.1 类
- 前面有文章介绍了使用GridView实现表格的方法,本文就来说说如何用ListView实现自适应的表格。GridView比ListView更
- 简介本文用示例介绍SpringBoot如何解决BigDecimal传到前端后精度丢失问题。问题描述实例Controllerpackage c
- 扫雷游戏,大家都应该玩过吧!其实规则也很简单,可是我们想自己实现一个扫雷,我们应该怎么做呢?Step1: 知晓游戏原理扫雷就是要把所有非地雷
- mapper.xml中if标签test判断的用法1. 字符串等于条件的两种写法① 将双引号和单引号的位置互换<if test='
- 前言Spring 事务注解 @Transactional 本来可以保证原子性,如果事务内有报错的话,整个事务可以保证回滚,但是加上try c
- 匿名内部类:先举个例子吧,给大家看一下什么是匿名内部类,Endeavor刚刚接触的时候,觉得哇哦,好奇怪的样子,这也太别扭了吧,不知道大家是
- OKhttp3中的cookiesOkHttpClient client = new OkHttpClient().newBuilder().
- /// <summary> /// 队列多线程,T 代表处理的单个类型~&nbs
- 使用IDEA开发微服务项目,需要启动多个微服务,可以开启IDEA的Run DashBoard窗口,需要对IDEA中指定工程的父工程进行配置进
- 最近由于项目需求,项目中需要实现一个WebSSH连接终端的功能,由于自己第一次做这类型功能,所以首先上了GitHub找了找有没有现成的轮子可
- 目录引言简单遍历筛选符合某属性条件的List集合获取某属性返回新的List集合获取以某属性为key,其他属性或者对应对象为value的Map
- 本文介绍了Android 删除所有build编译文件,翻译磁盘空间,分享给大家,也给自己留个笔记,具体如下: public static v