JDK11 | 第六篇 : Epsilon 垃圾收集器
文章首发于公众号《程序员果果》
一、简介
Epsilon(A No-Op Garbage Collector)垃圾回收器控制内存分配,但是不执行任何垃圾回收工作。一旦java的堆被耗尽,jvm就直接关闭。设计的目的是提供一个完全消极的GC实现,分配有限的内存分配,最大限度降低消费内存占用量和内存吞吐时的延迟时间。一个好的实现是隔离代码变化,不影响其他GC,最小限度的改变其他的JVM代码。
二、使用场景
- Performance testing,什么都不执行的GC非常适合用于差异性分析。no-op GC可以用于过滤掉GC诱发的新能损耗,比如GC线程的调度,GC屏障的消耗,GC周期的不合适触发,内存位置变化等。此外有些延迟者不是由于GC引起的,比如scheduling hiccups, compiler transition hiccups,所以去除GC引发的延迟有助于统计这些延迟。
- Memory pressure testing, 在测试java代码时,确定分配内存的阈值有助于设置内存压力常量值。这时no-op就很有用,它可以简单地接受一个分配的内存分配上限,当内存超限时就失败。例如:测试需要分配小于1G的内存,就使用-Xmx1g参数来配置no-op GC,然后当内存耗尽的时候就直接crash。
- VM interface testing, 以VM开发视角,有一个简单的GC实现,有助于理解VM-GC的最小接口实现。它也用于证明VM-GC接口的健全性。
- Extremely short lived jobs, 一个短声明周期的工作可能会依赖快速退出来释放资源,这个时候接收GC周期来清理heap其实是在浪费时间,因为heap会在退出时清理。并且GC周期可能会占用一会时间,因为它依赖heap上的数据量。
- Last-drop latency improvements, 对那些极端延迟敏感的应用,开发者十分清楚内存占用,或者是几乎没有垃圾回收的应用,此时耗时较长的GC周期将会是一件坏事。
- Last-drop throughput improvements, 即便对那些无需内存分配的工作,选择一个GC意味着选择了一系列的GC屏障,所有的OpenJDK GC都是分代的,所以他们至少会有一个写屏障。避免这些屏障可以带来一点点的吞吐量提升。
三、案例
使用G1垃圾收集器
代码:
public class TestEpsilon { public static void main(String[] args) { System.out.println("程序开始"); boolean flag = true; List<Garbage> list = new ArrayList<>(); long count = 0; while (flag) { list.add(new Garbage(list.size() + 1)); if (list.size() == 1000000 && count == 0) { list.clear(); count++; } } System.out.println("程序结束"); } } class Garbage { private int number; public Garbage(int number) { this.number = number; } /** * GC在清除对象时,会调用finalize()方法 */ @Override public void finalize() { System.out.println(this + " : " + number + " is dying"); } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } }
启动参数:
-Xms100m -Xmx100m
运行程序后,结果如下:
程序开始 ... com.gf.demo8.Garbage@15ddf76b : 305097 is dying com.gf.demo8.Garbage@35e52705 : 305224 is dying com.gf.demo8.Garbage@32c14bc1 : 305362 is dying com.gf.demo8.Garbage@7521660a : 305705 is dying com.gf.demo8.Garbage@f3da16a : 305948 is dying com.gf.demo8.Garbage@13fc7287 : 306089 is dying at java.base/java.lang.ref.Finalizer.register(Finalizer.java:66) at java.base/java.lang.Object.<init>(Object.java:50) at com.gf.demo8.Garbage.<init>(TestEpsilon.java:28) at com.gf.demo8.TestEpsilon.main(TestEpsilon.java:14) ...
会发现G1一直回收对象,直到内存不够用。
使用Epsilon垃圾收集器
启动参数:
UnlockExperimentalVMOptions:解锁隐藏的虚拟机参数。
-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xms100m -Xmx100m
运行程序后,结果如下:
程序开始 Terminating due to java.lang.OutOfMemoryError: Java heap space
会发现很快就内存溢出了,因为Epsilon不会去回收对象。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
JDK11 | 第五篇 : 启动单个Java源代码文件的程序
文章首发于公众号《程序员果果》 地址 : https://mp.weixin.qq.com/s/h1L4FmzVSix434gVt8Fc7w 一、简介 JEP330-启动单文件代码程序(Launch Single-File Source-Code Programs),是JDK11中一个很不错的功能。这个功能允许你直接使用java解析器运行java代码,java文件会在内存中执行编译并且直接执行。唯一的约束在于所有相关的类必须定义在东一个java文件中。 二、实例 案例1 创建一个 Test.java 文件 ,代码如下: public class Test { public static void main(String[] args) { System.out.println("Test ..."); } } 执行上面的代码 jdk11之前 : javac Test.java java Test jdk11: java Test.java 结论:jdk11中,通过 java xxx.java 命令,就可直接运行源码文件程序,而且不会产生.class 文件。 案例2 问题:如果一个jav...
- 下一篇
JDK11 | 第七篇 : ZGC 垃圾收集器
文章首发于公众号《程序员果果》 地址 : https://mp.weixin.qq.com/s/gfdml-SfvhFdMXlAu-a61w 一、简介 Java 11包含一个全新的垃圾收集器--ZGC,它由Oracle开发,承诺在数TB的堆上具有非常低的暂停时间。 在本文中,我们将介绍开发新GC的动机,技术概述以及由ZGC开启的一些可能性。 那么为什么需要新GC呢?毕竟Java 10已经有四种发布多年的垃圾收集器,并且几乎都是无限可调的。 换个角度看,G1是2006年时引入Hotspot VM的。当时最大的AWS实例有1 vCPU和1.7GB内存,而今天AWS很乐意租给你一个x1e.32xlarge实例,该类型实例有128个vCPU和3,904GB内存。 ZGC的设计目标是:支持TB级内存容量,暂停时间低(<10ms),对整个程序吞吐量的影响小于15%。 将来还可以扩展实现机制,以支持不少令人兴奋的功能,例如多层堆(即热对象置于DRAM和冷对象置于NVMe闪存),或压缩堆。 二、GC术语 为了理解ZGC如何匹配现有收集器,以及如何实现新GC,我们需要先了解一些术语。最基本的垃圾收...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Hadoop3单机部署,实现最简伪集群
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS6,CentOS7官方镜像安装Oracle11G