本文引用的代码源自 Oracle 博客上有关 Epsilon GC 的示例代码。
在本文中,我们探讨了 Java 垃圾收集 (GC) 中一个特别有趣的选项,称为 Epsilon GC。这种垃圾收集算法以其显着特征而著称:它不执行垃圾收集。 Epsilon 垃圾收集器 (GC) 包含在 JDK 11 中。
但是如果垃圾收集器不收集,它有什么用呢? (不劳而获啊!!)
不,它实际上非常有用,Oracle 博客提供的这样一个用例,我对其进行了稍微增强以使其更有帮助。
更多详情请参考原博文:
https://blogs.oracle.com/javamagazine/post/epsilon-the-jdks-do-nothing-garbage-collector
用例:Epsilon GC 对于需要在不借助分析工具的情况下评估特定代码段的内存分配的开发人员来说是有益的。
主要挑战传统的垃圾收集器可以通过不断清除对象来掩盖准确的内存使用指标。这种干扰使得很难确定代码的真实内存消耗。
Epsilon GC 通过充当非收集器来解决此问题。虽然它本身不是垃圾收集算法,但它通过避免执行任何垃圾收集来充当理解内存分配的工具,从而提供内存使用情况的清晰图片。
注意:需要注意的是,由于 Epsilon GC 不会回收内存,因此过多的分配可能会导致 JVM 中出现 OutOfMemoryError (OOM)。
下面是用于演示 Epsilon GC 功效的示例代码:
public class EpsilonDemo { public static String formatSize(long v) { if (v < 1024) return v + " B"; int z = (63 - Long.numberOfLeadingZeros(v)) / 10; return String.format("%.1f %sB", (double)v / (1L << (z*10)), " KMGTPE".charAt(z)); } public static void printmem(){ System.out.println("*** Free MEM = "+formatSize(Runtime.getRuntime().freeMemory())); } public static void main(String[] args) { final int MEGAABYTE = 1024 * 1024; final int ITERATIONS = 80; System.out.println("Starting allocations..."); printmem(); // allocate memory 1MB at a time for (int i = 0; i < ITERATIONS; i++) { var array = new byte[MEGAABYTE]; } System.out.println("Completed successfully"); printmem(); } }
期望:
该代码分配 80MB 的字节类型对象。当我们执行代码时,我们应该能够通过打印语句观察到相同的情况。
现在运行带/不带 EpsilonGC 的编译版本:
java -Xms100m -Xmx100m -XX:+UseG1GC EpsilonDemo Starting allocations... *** Free MEM = 102.2 MB Completed successfully *** Free MEM = 74.2 MB
因此,通过 G1GC,我们看到了 28 MB 利用率的错误分配图
java -Xms100m -Xmx100m -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC EpsilonDemo [0.004s][warning][gc,init] Consider enabling -XX:+AlwaysPreTouch to avoid memory commit hiccups Starting allocations... *** Free MEM = 99.4 MB Completed successfully *** Free MEM = 18.7 MB
在这里您可以清楚地看到 80.7 MB 的利用率
我希望这可以帮助您了解 EpsilonGC 如何非常方便地发现代码中的内存使用模式。干杯! ?
以上是使用 Java EpsilonGC 查看内存分配。的详细内容。更多信息请关注PHP中文网其他相关文章!