堆内存、本地内存、堆外内存、直接内存的区别
堆内存、本地内存、堆外内存、直接内存的区别
- 堆内存(Heap memory):堆内存是 JVM 进程内的内存,用于存储 Java 对象,并由 JVM 的垃圾回收器管理。
- 本地内存/堆外内存(Native memory/Off-heap):这是在进程地址空间中分配的内存,但不在堆内存范围内,因此不会被 Java 垃圾回收器释放。
- 直接内存(Direct memory):直接内存与本地内存类似,但它还意味着底层硬件中的缓冲区正在被共享。例如,网络适配器或图形显示中的缓冲区。这里的目的是减少相同字节在内存中被复制的次数。
区分堆内存、非堆内存的核心区别就是是否受jvm垃圾收集器管理
堆外内存和本地内存的联系和区别:
联系:
- 堆外内存实际上是本地内存的一部分,主要用于存储那些不需要被垃圾回收的对象或数据。
- 它们都位于 JVM 堆之外,不受垃圾回收器管理。
区别:
- 堆外内存更侧重于应用程序显式分配和使用的内存区域,通常是为了提高性能或减少垃圾回收的影响。
- 本地内存是一个更广泛的概念,涵盖了 JVM 进程中所有非堆内存区域,包括 JVM 自身使用的内存和其他本地资源。
你可以认为堆外内存是本地内存的一个子集,专门用于应用程序显式管理和使用的内存区域。
在实际开发中,当你提到“堆外内存”时,通常指的是你通过编程手段(如 Direct ByteBuffer 或其他方式)显式分配的内存;而“本地内存”则可能包含更多 JVM 自身使用的内存区域。
因此,在大多数情况下,堆外内存和本地内存可以视为相同的概念,但在具体场景下,它们的侧重点有所不同。
- 代码缓存Code Cache,既不在堆中,也不在元空间中,是一个单独的堆外区域。
- 如果启用了 类指针压缩 UseCompressedClassPointers,那么类及其元数据会使用两块独立的本地内存区域。在 UseCompressedClassPointers 模式下,64 位的类指针会被表示为 32 位值,这些压缩后的类指针存储在压缩类空间 (Compressed Class Space) 中。默认情况下,这个压缩类空间大小为 1GB,并且可以通过参数 CompressedClassSpaceSize 进行配置。
MaxMetaspaceSize 设置了这两块区域(压缩类空间的已提交空间和类元数据空间)的总提交大小的上限。
以下是启用 UseCompressedClassPointers 后 GC 日志中的示例输出。Metaspace 报告的已提交和已保留空间中,包含了压缩类空间的已提交和已保留空间。
Refer:
堆内存、本地内存、堆外内存、直接内存的区别