直接内存是从java 1.4开始引入的。新的I / O(NIO)类引入了一种基于通道和缓冲区执行I / O的新方法。 NIO增加了对直接ByteBuffers的支持,它可以直接传递给本机内存而不是Java堆。在某些情况下使它们显着更快,因为它们可以避免在Java堆和本机堆之间复制数据。
我永远不明白为什么我们使用直接记忆。有人可以帮忙举个例子吗?
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
我永远不明白为什么我们使用直接记忆。有人可以帮忙举个例子吗?
所有系统调用(如读取和写入套接字和文件)仅使用本机内存。他们不能使用堆。这意味着虽然您可以从堆中复制到本机内存或从本机内存复制,但避免此复制可以提高效率。
我们使用堆外/本机内存来存储我们的大多数数据,这些数据具有许多优点。
它没有被更多使用的原因是它更难以使它既高效又像普通的Java对象一样工作。出于这个原因,我们有像Chronicle Map这样的库,它们充当ConcurrentMap
但是使用堆外存储器,而Chronicle Queue则是一个日志,记录器和持久的IPC进程。