在Java中使用直接内存的目的是什么?

时间:2018-10-11 22:14:21

标签: java jvm

  

直接内存是从Java 1.4开始引入的。新的I / O(NIO)类引入了一种基于通道和缓冲区执行I / O的新方法。 NIO增加了对直接ByteBuffers的支持,可以直接传递给本机内存而不是Java堆。在某些情况下,使它们显着更快,因为它们可以避免在Java堆和本机堆之间复制数据。

我从不明白为什么我们要使用直接记忆。有人可以帮忙举个例子吗?

2 个答案:

答案 0 :(得分:3)

  

我从不明白为什么我们要使用直接记忆。有人可以帮忙举个例子吗?

所有系统调用(例如读写套接字和文件)仅使用本机内存。他们不能使用堆。这意味着尽管您可以从堆中复制本机内存或从中复制本机内存,但是避免此复制可以提高效率。

我们使用堆外/本机内存来存储我们的大多数数据,这具有许多优势。

  • 它可以大于堆大小。
  • 它可以大于主内存。
  • 它可以在JVM之间共享。即一个副本用于多个JVM。
  • 它可以在JVM甚至机器重新启动时被持久保存和保留。
  • 它对GC暂停时间几乎没有影响。
  • 取决于使用情况,它可能会更快

之所以不使用它,是因为很难使其既高效又像普通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