返回

JVM 的堆外内存分配与回收

后端

--------------------------------------------------------------------------
                   |                      |                      |
                   |  Heap(堆内存)         |   Non-Heap(非堆内存)   |
                   |                      |                      |
--------------------------------------------------------------------------

堆内存               Direct Memory          Shared Memory    Mapped Memory
                     OutOfMemoryError               OutOfMemoryError
                   |                      |                      |
--------------------------------------------------------------------------

JVM 内存模型

在JVM中,内存被分成两大块:堆内存和堆外内存。

  • 堆内存:堆内存是JVM使用的内存,用于存储对象实例和数组。
  • 堆外内存:堆外内存就是非JVM使用的内存,一般是分配给机器使用的内存。

堆外内存可以分为以下三种类型:

  • Direct Memory:直接内存,由JVM直接分配和管理,不经过操作系统。
  • Shared Memory:共享内存,由多个进程共享的内存区域。
  • Mapped Memory:映射内存,将文件或其他资源映射到内存中。

堆外内存分配

JVM可以通过以下方式分配堆外内存:

  • Direct Memory:使用Unsafe类中的allocateMemory()方法直接分配内存。
  • Shared Memory:使用POSIX shm_open()或Windows CreateFileMapping()函数分配共享内存。
  • Mapped Memory:使用POSIX mmap()或Windows CreateFileMapping()函数将文件或其他资源映射到内存中。

堆外内存回收

JVM可以通过以下方式回收堆外内存:

  • Direct Memory:使用Unsafe类中的freeMemory()方法释放内存。
  • Shared Memory:使用POSIX shm_unlink()或Windows CloseHandle()函数释放共享内存。
  • Mapped Memory:使用POSIX munmap()或Windows UnmapViewOfFile()函数释放映射内存。

OutOfMemoryError

如果JVM无法分配足够的堆外内存,就会抛出OutOfMemoryError异常。这通常是由于以下原因造成的:

  • Direct Memory:使用了过多的直接内存,导致JVM无法分配足够的内存。
  • Shared Memory:使用了过多的共享内存,导致JVM无法分配足够的内存。
  • Mapped Memory:使用了过多的映射内存,导致JVM无法分配足够的内存。

结论

堆外内存对于JVM来说非常重要,因为它可以提供更大的内存空间,从而提高应用程序的性能。但是,堆外内存也需要谨慎使用,因为如果使用不当,可能会导致OutOfMemoryError异常。因此,在使用堆外内存时,需要仔细考虑应用程序的实际需求,并采取适当的措施来避免内存溢出。