堆外内存是 Java/JVM 标准吗?

问题描述

我正在阅读 HBase 文档并遇到了 Off-heap read path 据我所知,堆外是内存中的一个地方,Java 将字节/对象存储在垃圾收集器的范围之外。我还搜索了一些有助于使用堆外内存的库,并找到了 Ehcatche 但是,我无法从 oracle 或 JVM 中找到任何关于他的官方文档。那么这是 JVM 的标准功能还是某种黑客行为,如果是这样,那么用于执行此操作的底层类和技术是什么?

解决方法

你应该寻找ByteBuffer

直接与非直接缓冲区

字节缓冲区要么是直接的,要么是非直接的。给定一个直接字节 缓冲区,Java 虚拟机将尽最大努力执行 直接在其上执行本机 I/O 操作。也就是说,它将尝试 避免将缓冲区的内容复制到(或从)中间缓冲区 在每次调用其中一个基础操作之前(或之后) 系统的原生 I/O 操作。

可以通过调用allocateDirect来创建直接字节缓冲区 这个类的工厂方法。此方法返回的缓冲区 分配和解除分配成本通常比 非直接缓冲区。 直接缓冲区的内容可能驻留在外部 正常的垃圾收集堆,以及它们对 应用程序的内存占用可能并不明显。这是 因此建议直接缓冲区主要分配给 受底层系统影响的大型、长期存在的缓冲区 本机 I/O 操作。一般来说最好直接分配 仅当它们在程序中产生可测量的增益时才缓冲 性能。

也可以通过映射文件的区域来创建直接字节缓冲区 直接进入内存。 Java 平台的实现可以 可选择支持从本机创建直接字节缓冲区 通过 JNI 的代码。如果这些类型的缓冲区之一的实例引用 到无法访问的内存区域,然后尝试访问该区域 region 不会改变缓冲区的内容,并且会导致 在访问时抛出的未指定异常或 稍后。

一个字节缓冲区是直接的还是非直接的可以由 调用它的 isDirect 方法。提供此方法以便显式 缓冲区管理可以在性能关键代码中完成。

它如何处理直接 ByteBuffer 取决于 JVM 实现,但至少 OpenJDK JVM 是在堆外分配内存。

JEP 383: Foreign-Memory Access API (Second Incubator) 特征是 incubating 中的 Java 15。此功能将通过提供公共 API 来访问堆外内存标准。