【问题标题】:More flexible memory management更灵活的内存管理
【发布时间】:2017-03-01 19:03:55
【问题描述】:

过去,我使用 C++ 或 C# 制作了大部分内存和性能关键应用程序,但随着 Java 语言的最新改进,我想我可以尝试一下。但是,我已经很早就陷入了 Java 中的内存管理。更具体地说,以下两点确实让我感到惊讶:

  • 为什么我必须告诉 JVM 它可以使用多少内存?就不能随便用吗?我的意思是...拿走你需要的东西?
  • 为什么对内存如此贪婪?将内存还给操作系统难道不能更慷慨一点吗?检查以下示例:

我上面提到的例子:

  • 从 2048mb 的堆空间开始
  • 在 T0 时刻,应用程序使用了 300mb 的 RAM
  • 我打开一个 400mb 文件 -> 700mb RAM 并完全读取到一个字节数组
  • 我将该数组包装到一个 ByteBuffer -> 700mb 的 RAM
  • 我将它解密为第二个数组(不能原地完成)-> 1100mb 的 RAM
  • 我关闭文件并清除 ByteBuffer 并将加密数组设置为 null -> 1100mb 的 RAM
  • 我解析解密后的数组(产生的数据少一点)-> 1350mb 的 RAM
  • 我将解密后的数组设置为 null -> 1350mb 的 RAM
  • 我等了一会儿 -> 1350mb 内存
  • 如果我用 1028mb 的堆空间重复上述操作 -> OutOfMemoryException

所以我的问题是:为什么 Java 会这样?更重要的是,我可以告诉 JVM 更……理智一点吗? C# 也是一种托管语言,但它能够正确释放未使用的内存。

【问题讨论】:

  • 为什么你认为你必须告诉JVM它应该使用多少内存......?你来这里是为了吐槽吗?
  • 我不确定你的评论,@Tunaki。我特别不想告诉它应该使用多少内存。我希望它尽可能少地使用它。它已经尽可能多地使用它,但遗憾的是它没有做第二个。

标签: java memory


【解决方案1】:

为什么我必须告诉 JVM 它可以使用多少内存?

你没有。它有一个合理的默认最大值,即主内存的 1/4,最高可达 32 GB。

它不能随心所欲地使用它吗?

可以,您可以将最大值设置为所有可用内存。

我的意思是...拿走你需要的东西?

它会这样做,但要达到您设置的某个最大值,因此它不会影响其他应用程序。

为什么它对记忆如此贪婪?

这取决于你如何使用它。

在向操作系统返还内存方面不能更慷慨一点吗?

这取决于您使用的 GC。

从 2048mb 的堆空间开始

我假设您的意思是 2 GB 或 2048 MB(mb 是毫位,对不起,我很讨厌)

这些天来这是一个非常小的内存量,我认为这只是一个例子。参考文献我 9 岁的孩子有一个我的旧台式机,内存为 24 GB。

我打开一个 400mb 的文件并完全读取到一个字节数组 -> 700mb 的 RAM

我会内存映射文件。这几乎不使用堆。顺便说一句,您也可以在 C 和 C# 中进行内存映射,这不是 Java 特有的技巧。

我将该数组包装到一个 ByteBuffer -> 700mb 的 RAM

内存映射文件已经是 ByteBuffer。在这一点上,你的堆不再大了。

我将它解密为第二个数组(不能原地完成)-> 1100mb 的 RAM

我会对另一个“直接”缓冲区执行此操作。再次没有使用更多的堆。

我解析解密后的数组(产生的数据少一点)-> 1350mb 的 RAM

所以这使用了额外的 250 MB。

我将解密后的数组设置为 null -> 1350mb 的 RAM

这会将引用更改为null,但没有其他内容。无论如何,这只是您上面的缓冲区之一。

我等了一会儿 -> 1350mb 的 RAM

如果你什么都不做,你就不会期望任何事情发生。

如果我用 1028mb 的堆空间重复上述操作 -> OutOfMemoryException

这是因为你保留了记忆,而第二次你的记忆变少了。

简而言之,我会

  • 使用内存映射文件。
  • 使用本机缓冲区
  • 请注意,如果确实需要,您可以确定性地清除这些,但通常不需要。
  • 除非需要,否则不要触及最大堆。

更重要的是,我可以告诉 JVM 更...理智一点吗?

我怀疑“理智”在旁观者的眼中。

【讨论】:

  • 为什么使用 1/4 是合理的数量?如果我有 32gb 的 RAM,应用程序最终应该使用多达 32gb 的 RAM,如果它真的需要 32gb 的 RAM,并且如果它不再需要它,最终也将它还给操作系统。我确实喜欢这样的想法,即您可以告诉应用程序最多可以使用多少,但是如果它更灵活一点并且也考虑其他应用程序,那就太好了。除了您的消息之外,我认为唯一直接的解决方案是再次使用本机内存管理并像使用非托管语言一样自行处理?
  • 我可能还忘了提到的是,我只是在谈论桌面应用程序,而不是服务器应用程序。
  • @Cromon Java 旨在运行在具有其他应用程序的机器上,除非您真的想要,否则任何程序都不应该使用机器的所有资源。
  • @Cromon 你不需要再自己处理了。
  • @Cromon Java 往往是为服务器设计的,而不是为一个用户设计的桌面。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-21
相关资源
最近更新 更多