JDK13新增了5个特性,有三个都比较容易理解和演示,比如textblock,swicth表达式增加yield,底层的Socket实现变为新的NIO实现。ZGC和动态的CDS归档则一直没有学习。
最近自己技术实在是有点不上心,没怎么去总结相关的技术内容。这次来看下所谓的ZGC到底是什么
介绍
JEP 351,ZGC,返回没有使用到的JVM堆内存给操作系统。关于JVM内存模型的介绍,参考:多线程之Java内存模型(JMM)
在JDK11的时候引入的ZGC,但是当前的ZGC并没有返回内存给系统,尽管有很长的时间内存都没有用到,但其实在一些应用中,并不需要一直占据大量的内存。只需要临时用到一次大内存,然而为了某一次的内存考虑,一直占用着系统的资源并不太合适。
当然有些应用并不需要用到回收内存,比如现在公司各个业务线在运行的应用,涉及到商业的内容,哪怕多占用一些内存,也不愿出现内存溢出的风险,所以ZGC只有在特定的场合下才会有用。
描述
ZGC是由许多的叫做ZPages的堆区域组成的,每一个ZPage绑定到不同大小的被使用的堆内存上。当ZGC压缩内存的时候,Zpages被清空,然后插入到Page Cahe中,叫做ZPageCache。在ZpageCache的Zpage都是可以随时准备被重新使用,满足堆内存的需要,当被使用的时候,会从ZpageCache中被移除出来。ZpageCache是对性能要求比较高,committing和uncommitting内存都是消耗比较高的操作。

在ZPageCache中的内存可以看做是还没有被使用到的内存,可以被重新uncommitted然后返回给操作系统。从Zpagecache中移除内存是比较简单和直接的,pageCache使用LRU算法存储ZPages,然后分为了隔离的大小(小,中,大),因此移除PageCache中的内存比较直接。难点在于需要设计一个合理的策略来判判断在什么时间点从pageCache中移除Zpage
最简单的方式是指定一个超时的时间,每一个Zpage可以在pagecache中存在多久的时间,超时的时间必须是一个合理默认值,也可以通过命令行选项来指定这个参数。
The Shenandoah GC uses a policy like this, with a default value of 5 minutes and the command line option
-XX:ShenandoahUncommitDelay=<milliseconds>
to override the default.
还有一种方式看起来也比较合理,在复杂的场景下,根据GC的频率来决定一个合理的超时时间,在程序运行的时候Zpage的超时时间是会动态变化的,我们只能在运行的时候设置一个初始值。
-XX:ZUncommitDelay=<seconds>
默认ZGC是可以归还内存给系统的,但是不管什么场景,都不会让堆内存小于指定的最小堆内存-Xms,如果我们在应用启动的时候最大内存和最小内存指定为一样的,那么代表着ZGC的uncommit能力是被禁止的。如果不想使用uncommit能力,也可以直接使用命令行参数-XX:-ZUncommit来禁止这个操作。
最后ZGC在Linux/64操作系统上,使用tmpfs或者hugetlbfs来归还内存,需要fallocate(2)和FALLOC_FL_PUNCH_HOLE的支持才行,这两个特性在Linux 3.5版本的时候出现的tmpfs,在Linux4.3的时候出现的hugetlbfs。
当前ZGC不支持老的Linux内核支持,如果在老的Linux系统上运行,禁用掉ZGC的uncommit内存能力。
注意:
- 当前在Mac系统上不能使用ZGC的特性
演示
- 下载JDK13 Linux版本
- 编写测试程序
public class HelloZGC {
public static void main(String[] args) {
System.out.println("Say hello to new low pause GC - ZGC!");
}
}
- 在JDK11之后,可以直接运行java文件,无需再编译为class文件后运行。
尝试开启ZGC运行程序
./bin/java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc* example/HelloZGC.java

- 如果程序运行时间较长,可以看出来uncommit内存的回收记录。
// 将gc日志记录到mylog.log文件
./bin/java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc:mylog.log* example/HelloZGC.java
参考:
网友评论