我在应用程序中以FileChannel.MapMode.READ_WRITE模式创建/使用内存映射文件。这些文件是在应用程序的整个生命周期中创建和删除的。
由于GC不一定要将直接缓冲区释放到_ unmap _底层OS缓冲区,我想知道在OS中会有什么后果,更具体地说,是关于RAM使用情况。
我知道进程的“虚拟内存”仍然受到不必要的映射的污染,但是对实际RAM使用的影响是什么呢(我猜“驻留内存”中的缓冲区会随着时间的推移而被刷新)。
似乎进程可以在操作系统级别(崩溃JVM)进行OOM (内存不足),而不是Java OOM (内存不足)(堆中仍有大量空间)。
我使用的是Linux 64位(3.13.0-68-generic / Ubuntu)机器,使用的是Oracle JRE 1.8.0_66-b17。
发布于 2015-12-06 14:42:59
地址空间是一种资源,您可以独立于可用内存(在某种程度上)耗尽它。
使用磁盘备份的文件映射,您只消耗与页面缓存(缓存读取和等待写入的脏页面)一样多的内存。但是保留的地址空间是整个映射的大小。
您还会消耗文件句柄,并且很可能会先用完这些句柄。
Java在munmap映射为GCed时执行它们--然而,这意味着它发生在GC的时间表上,而不是您的时间表上。这通常是可以的,只要它比您分配地址空间更快地释放地址空间即可。但就像文件描述符或任何其他有限资源一样,您肯定会用完。
使用64位,这将需要一段时间。这在32位系统上是一个更大的问题。
有很多人呼吁改进映射控制,因为依赖终结器并不是很好。但是,在不牺牲性能或安全性的情况下,很难做得更好。To quote Sun's evaluation of the problem
在映射的字节缓冲区上没有unmap()方法,因为没有已知的技术可以提供这样的方法,而不会遇到无法克服的安全和性能问题。
https://stackoverflow.com/questions/34113991
复制相似问题