java 可视化
像西洋双陆棋一样,垃圾收集需要花费几分钟的时间来学习,并且需要终生掌握。
在他的演讲“ 可视化垃圾收集”中,高级培训师/顾问Ben Evans从头开始讨论GC。
以下是他的演讲的简短摘要。
基本
当释放不再使用的内存时,GC在很大程度上取代了早期的技术,例如手动内存管理和引用计数。
这是一件好事,因为内存管理很无聊,计算机擅长的书呆子簿记,而人们却没有。 语言运行时在这方面比人类要好。
现代GC效率很高,远远超过早期语言中典型的手动分配。 来自其他语言背景的人们经常专注于GC暂停,而没有完全了解自动内存管理所处的环境。
Mark&Sweep是Java(和其他运行时)用于GC的基本算法。
在“标记和扫描”算法中,您具有从每个堆栈线程的框架指向的引用,这些引用指向程序堆。 因此,我们从堆栈开始,遵循指向所有可能引用的指针,然后递归地遵循这些引用。
完成后,您将拥有所有活动对象,而其他所有内容都是垃圾。
请注意,人们经常会忘记的一点是,运行时本身还具有指向每个对象的指针列表,称为“分配列表”,该列表由垃圾收集器维护并有助于垃圾收集器进行清理。 因此,运行时始终可以找到它创建但尚未收集的对象。
图1
上图中所示的堆栈只是与单个应用程序线程相关联的堆栈。 每个应用程序线程都有一个类似的堆栈,并且具有指向堆栈的自己的一组指针。
如果垃圾收集器试图获取应用程序运行时生活的快照,那么它将追逐一个移动的目标,并且很容易错过一些时间不正确的对象分配,并且无法获得准确的快照。 因此,有必要“停止世界”; 即停止应用程序线程足够长的时间以捕获活动对象快照。
垃圾收集器必须遵守两个黄金法则:
- 垃圾收集器必须收集所有垃圾。
- 垃圾收集器绝不能收集任何活动对象。
但是这些规则并不是平等的。 如果违反了规则2,则最终将导致数据损坏。
另一方面,如果违反了规则1,相反,我们有一个系统不能一直收集所有垃圾,而是最终只收集它,那么这是可以容忍的,实际上可以作为基础垃圾收集器。
热点
现在让我们谈谈HotSpot,它实际上是C和C ++的集合以及许多特定于平台的汇编程序。
人们想到口译员时,会想到带有大型switch语句的大型while循环。 但是HotSpot解释器要复杂得多(出于性能原因)。 当您开始查看JDK源代码时,就会意识到Hotspot中有多少汇编程序代码。
对象创建
在Java中,我们预先分配了大量连续的空间,这就是我们所说的“堆”。 然后,由HotSpot完全在用户空间中管理此内存。
如果您看到Java进程正在使用大量的系统(或内核)时间,那么您可以放心,它不会进行垃圾回收-因为我们所有的GC内存簿记都是在用户空间中完成的。
内存池
图2
PermGen是诸如类元数据之类的东西的存储区域,这些东西在程序的生命周期中需要保持活动状态。 但是,随着具有自己的类加载器并需要重新加载类元数据的应用服务器的出现,PermGen开始看起来像是一个糟糕的优化决策,幸运的是,在Java 8中该决策已不复存在。
将使用一个称为“元空间”的新概念,它与PermGen并不完全相同。 元空间在堆之外,并且由操作系统管理。 这意味着它将不进入Java堆,而是进入本机内存。 目前,这并不是一个好消息,因为没有太多工具可以让您轻松查看本机内存。 因此,PermGen消失是一件好事,但是要赶上该工具还需要一些时间。
Java堆布局
现在让我们看一下Java堆。 注意堆空间之间的虚拟空间。 这些提供了一些摆动,可以在不损失移动所有内容的代价的情况下调整池的大小。
图3
弱代假设
现在,为什么我们实际上将堆分成所有这些内存池?
图4
有些运行时事实无法通过静态分析得出。 上图说明了两组对象: 那些早逝的人和活了很久的人-因此有必要进行额外的簿记以利用这一事实。 Java平台上充斥着类似的事实,这些事实已作为优化被编入平台。
演示版
一系列动画的 演示 进行 。 Flash中的第一个演示说明了伊甸园和年轻一代幸存者空间之间的运动,最后演变为终身制。
图5呈现了相同的JavaFX。
图5
运行时开关
强制性标志
- -verbose:gc –给我一些GC输出
- -Xloggc:<pathtofile> –日志输出的路径,请确保您有磁盘空间
- -XX:+ PrintGCDetails –帮助工具的最少信息
–替换-verbose:gc与此
- -XX:+ PrintTenuringDistribution –过早的促销信息
基本堆大小标志
- -Xms <size> –设置为堆保留的最小大小
- -Xmx <size> –设置为堆保留的最大大小
- -XX:MaxPermSize = <大小> –设置perm生成的最大大小–适用于Spring应用程序和App服务器
在过去,我们被教导将–Xms设置为与–Xmx相同的值。 但是,这种情况已经改变。 现在,您可以将–Xms设置为相当小的值,或者根本不设置它,因为堆自适应性现在非常好。
其他标志
- -XX:NewRatio = N
- -XX:NewSize = N
- -XX:MaxNewSize = N
- -XX:MaxHeapFreeRatio
- -XX:MinHeapFreeRatio
- -XX:SurvivorRatio = N
- -XX:MaxTenuringThreshold = N
图6
为什么要记录文件
日志文件的优点是可以用于法医分析,这可以使您不必再次运行代码即可重现问题(如果这是罕见的生产错误,则不容易)。
与JMX MXBean相比,它们还具有更多的内存信息,更不用说轮询JMX会引入其自身的GC问题集。
工装
- HP JMeter(Google it)
–免费,相当可靠,但不再受支持/增强
–免费,OSS,但有点难看
–最好的名字
– J9支持
–最漂亮,最有用–但是我们有偏见!
综上所述
- 您需要了解一些基本的GC理论
- 您希望大多数物体在年轻一代中死掉
- 打开GC日志记录! –读取原始日志文件很困难–使用工具
- 使用工具来帮助您进行调整 –衡量,不要猜测
在这里您可以访问完整的演示文稿。
java 可视化