直接内存是从Java 1.4开始引入的。新的I / O(NIO)类引入了一种基于通道和缓冲区执行I / O的新方法。 NIO增加了对直接ByteBuffers的支持,可以直接传递给本机内存而不是Java堆。在某些情况下,使它们显着更快,因为它们可以避免在Java堆和本机堆之间复制数据。
我从不明白为什么我们要使用直接记忆。有人可以帮忙举个例子吗?
答案 0 :(得分:3)
我从不明白为什么我们要使用直接记忆。有人可以帮忙举个例子吗?
所有系统调用(例如读写套接字和文件)仅使用本机内存。他们不能使用堆。这意味着尽管您可以从堆中复制本机内存或从中复制本机内存,但是避免此复制可以提高效率。
我们使用堆外/本机内存来存储我们的大多数数据,这具有许多优势。
之所以不使用它,是因为很难使其既高效又像普通Java对象一样工作。因此,我们拥有像Chronicle Map这样的库,它们像ConcurrentMap
那样使用堆外内存,而Chronicle Queue是日志,记录器和进程间持久IPC。 >
答案 1 :(得分:2)
JVM依靠垃圾回收的概念来回收不再使用的内存。这使JVM语言开发人员(例如Java,Scala等)不必担心内存分配和释放。您只需请求内存,然后让JVM担心何时将其回收或进行垃圾回收。
尽管这非常方便,但是它带来了单独线程的额外开销,消耗CPU并不得不不断地遍历JVM堆,从而回收不再可访问的对象。有很多关于该主题的书,但是如果您想更多地了解JVM垃圾回收,那么这里有很多参考文献,但这是不错的:https://dzone.com/articles/understanding-the-java-memory-model-and-the-garbag
无论如何,如果在您的应用程序中,您知道将要进行大量的复制,更新对象和值,则可以选择自己处理这些对象及其内存消耗。因此,无论这些对象有多少搅动,这些对象都不会在堆中四处移动,也永远不会进行垃圾回收,因此不会影响JVM中的垃圾回收。这个答案还有更多细节:https://stackoverflow.com/a/6091680/236528
来自官方Javadoc:
直接缓冲区与非直接缓冲区
字节缓冲区是直接的还是非直接的。给定一个直接字节 缓冲区,Java虚拟机将尽最大努力执行 直接在其上进行本机I / O操作。也就是说,它将尝试 避免将缓冲区的内容复制到中间缓冲区(或从中间缓冲区复制) 每次调用一个基础操作之前(或之后) 系统的本机I / O操作。
可以通过调用
allocateDirect
来创建直接字节缓冲区 此类的工厂方法。此方法返回的缓冲区 通常分配和解除分配的费用比 非直接缓冲区。 直接缓冲区的内容可能驻留 在正常的垃圾收集堆之外,因此它们对 应用程序的内存占用可能并不明显。 因此建议直接缓冲区主要分配给 大型,长期存在的缓冲区受基础系统的约束 本机I / O操作。 通常最好直接分配 仅当它们在程序中产生可衡量的收益时才进行缓冲 性能。
https://download.java.net/java/early_access/jdk11/docs/api/java.base/java/nio/ByteBuffer.html