5

例如我这样一个代码

...获取一些内存并丢失所有指向该内存的指针,以便 System.gc(); 可以收集。

调用 System.gc();

做一些其他的任务;


这里做的是“做一些其他的任务;” 和“System.gc();” 并行工作或“做一些其他任务”;等待“System.gc();” 被执行

谢谢

4

9 回答 9

7

您可能不应该使用 System.gc()。使用 Java 的 C/C++ 用户的一个常见误解是他们认为他们需要告诉虚拟机何时可以执行垃圾收集。现实情况是垃圾收集器经过高度优化,并在认为最好的时候自行执行此任务。通常不建议调用 System.gc()。

但是,如果您确实调用 System.gc(),它会“建议”系统执行垃圾收集。尽管通常会执行,但它实际上可能不会执行收集。是否在另一个线程中运行取决于实际的收集算法。默认设置将在运行时阻止所有内容。所以它可能在单独的线程中运行,但它会阻止你当前的执行。

于 2010-04-19T12:24:26.367 回答
6

这里的确切行为完全取决于 JVM 实现。在规范中(这是正确的 JVM 实现需要为您提供的),它可以并行发生,它可以在您的代码执行之前首先发生,或者根本不会发生。

在实践中,我对碰巧观察到的 JVM 的观察是它立即在单独的线程中运行。但是,在某些情况下,多个调用会产生多个线程,有时它会将请求排队在一个线程上。启动的垃圾收集始终是“stop-the-world”类型(即它非常完整并且减慢或暂停了应用程序)。

但是,鉴于您对@Chris Dail 的评论,您的根本问题不是 System.gc() 调用的行为。调用 System.gc() 可以有一些用途。它可以用于清除内存,因此您可以了解当前应用程序的实际占用空间有多大。它还可以用作一种策略,以确保更早地发生 stop-the-world 垃圾收集,以便它在更短的时间内“停止世界”,因为要清除的内存更少。(我应该注意到,随着 JVM 变得越来越复杂,这种事情越来越没有必要,实际上会适得其反)。

然而,它不以任何方式解决 OutOfMemoryError。JVM 不会给你一个 OutOfMemoryError,直到它尽其所能收集垃圾。调用 System.gc 不会改变这一点。如果您有 OutOfMemoryError,很可能是因为您以您并不真正需要的方式持有对对象的引用,但这会阻止这些对象的内存被回收。

于 2010-04-19T13:04:43.920 回答
4

它通常是同步的,但不能保证。

实际上,既不能保证收集会有效地发生,因为 JVM 将决定它是否有意义以及使用哪种垃圾收集。

如果您需要更多信息,您可以使用-verbosegcflag 启动您的程序。

在任何情况下,垃圾收集都是由 JVM 自动发出的,没有任何指定的调用,调用System.gc()只是你给它的一个提示,让它知道它可能会启动一个收集。

于 2010-04-19T12:25:41.473 回答
1

垃圾收集的执行方式取决于 JVM 实现。通常的实现可能会停止所有线程,以全局收集内存,例如仅停止一个线程以为此线程收集本地内存。阅读来自Sun的更多关于垃圾收集的信息以及这篇较早但很好的文章

于 2010-04-19T12:26:52.113 回答
1

正如Eric Eijkelenboom 所指出的,调用此方法并不意味着垃圾收集器将立即执行。其实你根本不知道它是否会被调用......

在您的情况下(从对Amarghosh的回答的评论来看),您需要在执行需要大量 RAM 的操作之前释放一些内存,对吗?在这种情况下,您无需担心。如果有足够的内存进行垃圾收集,当您尝试分配它时会自动完成。

于 2010-04-19T12:28:04.743 回答
0

“做一些其他任务”等待System.gc()执行并返回。

于 2010-04-19T12:21:37.987 回答
0

没有办法知道。调用System.gc()并不意味着在那一秒执行垃圾收集,它只是被调度。由 JVM 在合适的时间执行垃圾收集。

于 2010-04-19T12:23:17.253 回答
0

javadoc 告诉http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#gc():“当控制从方法调用返回时,Java 虚拟机已经尽最大努力从所有丢弃的对象中回收空间。

所以我会说“做一些其他的任务”;等待“System.gc();” 被执行!

没有使用并行性——这对 Java 应用程序不利。事实上,调用/强制垃圾收集器从来都不是一个好主意。它必须保留在没有其他解决方案的极端情况下......

再见,奥尔本。

于 2010-04-19T12:28:39.233 回答
0

根据 Java 规范,调用 System.gc()的线程会停止,直到 GC 完成它的行为。请注意,这只是一个提示,JVM 可以随意忽略它,Sun 的 JVM 实际上有一个命令行开关 ( -XX:-DisableExplicitGC) 来实现这一点。使用此开关,System.gc()什么都不做并立即返回。

无论哪种方式,规范中的任何内容都不会阻止其他线程运行。这取决于GC算法;Sun 的 JVM 包括几个,其中一些能够与应用线程同时运行以完成大部分工作。

正如其他人所指出的,在System.gc()大多数情况下,显式调用的净效果是降低性能。如果你觉得你必须调用那个方法,那么很可能你做错了什么。

于 2010-04-19T15:22:58.923 回答