更灵活的内存管理

时间:2017-03-01 19:03:55

标签: java memory

在过去,我使用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的RAM
  • 如果我用1028mb的堆空间重复上述内容 - > OutOfMemoryException异常

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

1 个答案:

答案 0 :(得分:4)

  

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

你没有。它的合理默认最大值为主存储器的1/4,最大为32 GB。

  

难道不能只使用它想要的东西吗?

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

  

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

它可以做到这一点,但是你设置的最大值不会影响其他应用程序。

  

为什么内存如此贪婪?

这取决于你如何使用它。

  

在向操作系统回放内存方面有多慷慨吗?

这取决于您使用的GC。

  

开始使用2048mb的堆空间

我认为你的意思是2 GB或2048 MB(mb是一个毫位,而且我很讨厌我的抱怨)

现在这是一个非常少量的内存,我想这只是一个例子。 C.F.我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多一点......理智吗?

我怀疑“理智”是旁观者的眼睛。