System.gc()
,JVM可能会决定在那个时刻进行或不进行垃圾回收。这是如何精确工作的?JVM基于什么准则/参数来决定是否执行GC,当它看到System.gc()
时?是否有任何例子表明将此放入代码中是一个好主意?
System.gc()
,JVM可能会决定在那个时刻进行或不进行垃圾回收。这是如何精确工作的?JVM基于什么准则/参数来决定是否执行GC,当它看到System.gc()
时?实际上,它通常会决定执行垃圾回收。答案因许多因素而异,如您正在运行的JVM、所处模式以及使用的垃圾回收算法。
我不建议在代码中依赖它。如果JVM即将抛出OutOfMemoryError,调用System.gc()不会阻止它,因为垃圾收集器会尽可能释放更多内存,直到极限。我见过它被用于IDE中,那里附有一个用户可以点击的按钮,但即使在那里,它也不是非常有用。
System.gc()
方法。此时,我并不介意这个调用是否清除了所有可能的东西,甚至什么也没做。然而,我更希望它在加载界面期间“努力回收未使用的对象”,而不是在游戏进行时进行回收。 - Kröw在Java中,垃圾回收是由虚拟机决定的,您无法对其进行控制。我从未遇到过需要使用System.gc()
的情况。由于System.gc()
调用只是暗示虚拟机执行垃圾回收,并且它会执行一个完整的垃圾回收(在多代堆中包括老年代和新生代),因此它实际上可能会消耗比必要更多的CPU周期。
在某些情况下,建议虚拟机立即进行一次完整的垃圾回收可能是有意义的,例如您知道应用程序在接下来的几分钟内将处于空闲状态,然后会产生大量工作负载。例如,在应用程序启动期间初始化了大量临时对象之后(即,我刚刚缓存了大量信息,并且我知道在接下来的一分钟或更长时间内不会有太多活动)。想象一下像Eclipse这样的IDE启动 - 它需要进行很多初始化操作,因此在初始化之后立即执行完整的垃圾回收可能是有意义的。
我唯一能想到需要调用System.gc()方法的情况是,在对一个应用程序进行性能分析以寻找可能的内存泄漏时。我相信性能分析器在捕获内存快照之前会调用这个方法。
Java语言规范并不保证在调用System.gc()
时JVM会启动GC。这就是为什么出现了“可能会决定在那个点上执行GC,也可能不会”的原因。
现在,如果您查看作为Oracle JVM骨干的OpenJDK源代码,您会发现调用System.gc()
确实会启动一个GC周期。如果您使用另一个JVM,例如J9,则必须查阅其文档以找到答案。例如,Azul的JVM具有连续运行的垃圾收集器,因此调用System.gc()
将不起作用。
一些其他答案提到通过JConsole或VisualVM启动GC。基本上,这些工具会远程调用System.gc()
。
通常,您不希望从代码中启动垃圾回收循环,因为它会破坏应用程序的语义。您的应用程序执行某些业务操作,JVM负责内存管理。您应该将这些问题分开处理(不要让应用程序执行一些内存管理操作,而是专注于业务)。
然而,在一些情况下,调用System.gc()
可能是可以理解的。例如,微基准测试。没有人希望在微基准测试中发生GC周期。因此,您可以在每次测量之间触发一次GC循环,以确保每个测量都以空堆开始。
如果您调用System.gc()
,需要非常小心。调用它可能会给您的应用程序增加不必要的性能问题,并且不能保证实际执行垃圾回收。实际上,可以通过Java参数-XX:+DisableExplicitGC
来禁用显式的System.gc()
。
我强烈建议阅读Java HotSpot Garbage Collection中提供的文档,以获取更深入的垃圾回收详细信息。
System.gc()
是由虚拟机(VM)实现的,它的具体功能取决于具体的实现。例如,实现者可能只是返回并不执行任何操作。
至于何时发出手动垃圾回收,唯一需要这样做的情况是当你放弃了一个包含大量小集合的大集合 - 比如一个 Map<String,<LinkedList>>
- 并且你想尝试在那时尽快处理性能问题,但大部分情况下,你不用担心。垃圾回收器通常比你更聪明。
ByteBuffer.allocateDirect()
并且出现OutOfMemoryError错误,则可以在手动触发GC后发现此调用是正常的。Cleaners
的快捷方式,用于直接内存使用。即使如此,如果您快速创建直接内存区域,仍然可能会出现OOME。解决方案是不要这样做,并尽可能重复使用您的直接内存区域。 - Peter Lawrey垃圾回收
在桌面/笔记本电脑/服务器中运行Java编写的软件时非常好用。在Java中,您可以调用System.gc()
或Runtime.getRuntime().gc()
。
请注意,这些调用都不能保证实现任何操作。它们只是向jvm建议运行垃圾回收器。是否运行GC取决于JVM。所以简短的答案是:我们不知道它何时运行。更长的答案是:如果JVM有时间,它会运行gc。
我认为,Android也是一样的。然而,这可能会减慢您的系统速度。
如果你想知道是否调用了System.gc()
,在新的Java 7更新4中,你可以获得JVM进行垃圾回收时的通知。
我不确定GarbageCollectorMXBean类是在Java 7更新4中引入的,因为我在发布说明中找不到它,但我在javaperformancetuning.com网站上找到了这些信息。