2

我有这样的问题,jvm 无法及时执行 gc 并且应用程序冻结。“解决方案”是使用 jconsole 连接到应用程序并建议 jvm 进行垃圾收集。我不必说这是非常糟糕的应用程序行为。jvm是否有一些选项可以建议它更快/更频繁地执行gc?也许这个问题还有其他真正的解决方案?

问题似乎不是内存不足,而是 gc 在新数据发送到应用程序之前无法及时收集。之所以如此,是因为 gc 似乎开始收集数据很晚。如果 jconsole 的 System.gc() 按钮足够早地建议,则不会出现问题。

年轻代由并行收集器“PS Scavenge”收集。老年代由并行标记和扫描收集器“PS MarkSweep”收集。

4

8 回答 8

2

您应该检查内存泄漏。我很确定除非没有要释放的内存并且没有更多可用内存,否则您不会得到 OutOfMemoryException。

于 2013-09-10T11:34:00.307 回答
2

System.gc()正是您所描述的:它向 JVM 建议应该进行垃圾收集。(JVM 还有一些命令行参数可以作为内存管理器的指令。)

但是,如果您在分配期间内存不足,则通常意味着 JVM确实首先尝试了垃圾收集,但未能释放必要的内存。在这种情况下,您可能有内存泄漏(在保留不必要的引用的意义上),您应该使用内存分析器来检查它。这很重要,因为如果您有内存泄漏,那么更频繁的垃圾收集将无法解决您的问题 - 除非它们可能会推迟它的表现,给您一种错误的安全感。


Java规范

OutOfMemoryError:Java 虚拟机实现已用完虚拟内存或物理内存,并且自动存储管理器无法回收足够的内存来满足对象创建请求。

于 2013-09-10T11:31:58.630 回答
1

您可以在您的服务器上部署java melody并在其上添加您的应用程序,它将为您提供有关内存泄漏和内存使用情况的详细报告。有了这个,您将能够正确优化您的系统和代码。

于 2013-09-10T11:33:26.953 回答
1

如果您的应用程序冻结,但被强制 GC 解冻,那么您的问题很可能不是内存,而是其他一些资源泄漏,这可以通过在死对象上运行终结器来缓解。正确编写的代码绝不能依赖终结器来进行清理,因此请尝试在应用程序中查找任何未关闭的资源。

于 2013-09-12T12:37:11.750 回答
1

此外,

如果您正在加载很多类(比如说,rt.jar 中存在的所有类),您可能会收到 OOME。由于加载的类驻留在 PermGen 而不是堆内存中,您可能还想使用 -XX:MaxPermSize 开关增加 PermGen 大小。

当然,您可以自由选择垃圾收集器——ParallelGC、ConcMarkSweepGC (CMS) 或 G1GC (G1)。

请注意,Java 中的 API 本身可能会导致内存泄漏(没有任何程序员的错误)——例如 java.lang.String#substring()(参见此处

于 2013-09-10T11:44:13.930 回答
1

我想,要么您的应用程序需要更多内存才能有效运行,请尝试通过设置参数来调整您的 JVM,例如-Xms512M -Xmx1024M. 或者,存在耗尽内存的内存泄漏。

您应该检查应用程序的内存消耗模式。例如,当它处理更多而不是保持空闲时它占用的内存。

如果您观察到内存峰值的持续激增,则可能表明可能存在内存泄漏。关于内存泄漏问题的最佳线程之一是如何找到 Java 内存泄漏

另一个不错的是http://www.ibm.com/developerworks/library/j-leaks/

于 2013-09-10T11:38:16.290 回答
0

你可以用更多内存启动jvm

java -Xms512M -Xmx1024M

将以 512Mb 的内存启动 jvm,使其增长到千兆字节。

于 2013-09-10T11:32:55.653 回答
0

您可以使用System.gc()建议 VM 运行垃圾收集器。不能保证它会立即运行。

我怀疑这是否会有所帮助,但它可能会奏效。您可以查看的另一件事是增加 JVM 的最大内存大小。您可以通过提供命令行参数来做到这一点-Xmx512m。这将提供 512 MB 的堆大小,而不是默认的 128。

您可以使用 JConsole 查看应用程序的内存使用情况。这有助于了解内存使用情况如何发展,这对于检测内存泄漏很有用。

于 2013-09-10T11:36:00.157 回答