java - Java中的突发内存使用

标签 java memory-management memory-leaks garbage-collection

我正在尝试在 Java 中处理正确的内存使用和垃圾收集。我无论如何都不是一个新手程序员,但在我看来,一旦 Java 触及某些内存,它就永远不会被释放以供其他应用程序使用。在这种情况下,您必须确保您的峰值内存永远不会太高,否则您的应用程序将继续使用任何峰值内存使用量。

我写了一个小示例程序试图证明这一点。它基本上有 4 个按钮...

  1. 填充类范围变量BigList = new ArrayList<string>()包含大约 25,000,000 个长字符串项。
  2. 调用 BigList.clear()
  3. 重新分配列表 - BigList = new ArrayList<string>()再次(缩小列表大小)
  4. 调用 System.gc() - 是的,我知道这并不意味着 GC 会真正运行,但这就是我们所拥有的。

接下来我在 Windows、Linux 和 Mac OS 上进行了一些测试,同时使用默认任务监视器检查进程报告的内存使用情况。这是我发现的...

  • Windows - 抽列表,调用 clear,然后调用 GC 几次,根本不会减少内存使用。但是,使用 new 重新分配列表然后多次调用 GC 会将内存使用量降低到起始水平。 IMO,这是可以接受的。
  • Linux(我将 Mint 11 发行版与 Sun JVM 一起使用)- 结果与 Windows 相同。
  • Mac OS - 我遵循了与上述相同的步骤,但即使重新初始化对 GC 的列表调用似乎也没有效果。即使我的内存中没有任何内容,该程序仍将占用数百 MB 的 RAM。

谁能给我解释一下?有人告诉我一些关于“堆”内存的东西,但我仍然不完全理解它,我不确定它是否适用于此。据我所知,无论如何,我不应该看到我在 Windows 和 Linux 上的行为。

这只是 Mac OS Activity 监视器测量内存使用情况的方式不同,还是发生了其他事情?我宁愿不要让我的程序因大量 RAM 使用而闲置。感谢您的洞察力。

最佳答案

Sun/Oracle JVM 不会将不需要的内存返回给系统。如果你给它一个很大的最大堆大小,并且你实际上在某个时候使用了那个堆空间,JVM 不会把它还给操作系统用于其他用途。其他 JVM 会这样做(JRockit 曾经这样做过,但我认为它不再这样做了)。

因此,对于 Oracles JVM,您需要调整您的应用程序和系统以达到峰值使用率,这就是它的工作原理。如果您正在使用的内存可以使用字节数组进行管理(例如处理图像或其他内容),那么您可以使用映射字节缓冲区而不是 Java 字节数组。映射字节缓冲区直接取自系统,而不是堆的一部分。当您释放这些对象时(我相信它们是 GC'd,但不确定),内存将返回给系统。假设它甚至完全适用,您可能不得不使用它。

关于java - Java中的突发内存使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8265240/

相关文章:

C++ - 重载赋值运算符内存泄漏

asp.net - ASP.NET 中 FileMonitorTarget/CacheDependency+DepFileInfo 的内存泄漏

java - 如何使用多个参数进行 Spring 构造函数注入(inject)

java - 编译 NanoVM Java 虚拟机

c# - C# 可以并将对象写入页面文件吗?

linux - 了解Linux中的进程内存映射

c - 作业 : I have a memory leak somewhere, 但我找不到它。关于如何更有效地使用 valgrind 的任何提示?

java - cucumber 报告不生成

Java Stream 与 JPA 一对多(LAZY)关系不起作用

c - 内存不足故障处理方法