ByteBuffer.allocateDirect() 和 MappedByteBuffer.load() 之间的区别

发布于 2024-07-29 13:54:52 字数 1206 浏览 5 评论 0原文

我试图通过使用 MappedByteBuffer 内存映射特定文件来实现两个或多个 JVM 之间的共享缓存。 从规范中我看到,当我们使用 MappedByteBuffer.load() 时,它应该将数据加载到直接缓冲区中。 我对此有几个问题。

我的代码片段::

RandomAccessFile file = new RandomAccessFile("file.txt","rw");
FileChannel fc = file.getChannel();
MappedByteBuffer buf5 = fc.map(MapMode.READ_WRITE, 0, fc.size());

//ByteBuffer buf6 = ByteBuffer.allocateDirect(100000000);

buf5.load();

try
{
    Class c = Class.forName("java.nio.Bits");
    Field f = c.getDeclaredField("reservedMemory");
    f.setAccessible(true);
    long reservedMemory = f.getLong(null);
    f = c.getDeclaredField("maxMemory");
    f.setAccessible(true);
    System.out.println(
            "Direct Memory Usage: "+ reservedMemory +"/"+ f.getLong(null)+"\n");
}
catch (Throwable t)
{
}
  1. 上述代码的输出是直接内存使用量为 0 字节(File.txt 为 1 GB)。 但如果我取消注释该行..

    ByteBuffer buf6 = ByteBuffer.allocateDirect(100000000); 
      

    我得到的直接内存使用量为 100MB 。 无法理解为什么会这样,至于为什么我一开始没有得到任何直接内存使用情况(即当该行被注释掉时)

  2. 尽管上述代码的直接内存使用量为 0 B,但我确实看到进程的驻留内存(使用 unix top )增加了 1 GB。 但是,如果我在盒子上执行“free -m”,我没有看到内存使用量有任何增加。

在这两种情况下,我都对内存的最终去向感到有点困惑。

谢谢!

I was trying to implement a sort of shared cache between two or more JVMs by memory mapping a particular file using MappedByteBuffer. From the specifications I see that when we use MappedByteBuffer.load() it should load the data into a direct buffer. I have a couple of questions on this.

My code snippet::

RandomAccessFile file = new RandomAccessFile("file.txt","rw");
FileChannel fc = file.getChannel();
MappedByteBuffer buf5 = fc.map(MapMode.READ_WRITE, 0, fc.size());

//ByteBuffer buf6 = ByteBuffer.allocateDirect(100000000);

buf5.load();

try
{
    Class c = Class.forName("java.nio.Bits");
    Field f = c.getDeclaredField("reservedMemory");
    f.setAccessible(true);
    long reservedMemory = f.getLong(null);
    f = c.getDeclaredField("maxMemory");
    f.setAccessible(true);
    System.out.println(
            "Direct Memory Usage: "+ reservedMemory +"/"+ f.getLong(null)+"\n");
}
catch (Throwable t)
{
}
  1. The output of the above code is 0 byte for the Direct Memory Usage (File.txt is 1 GB). But if I uncomment the line ..

    ByteBuffer buf6 = ByteBuffer.allocateDirect(100000000);
    

    I get a Direct Memory Usage of 100MB . Not able to understand why is this so, as to why I am not getting any direct memory usage in the first place ( i.e. when the line is commented out )

  2. Although the Direct Memory Usage is 0 B for the above code, I do see that the resident memory ( using unix top ) of the process increase by 1 GB. But if I do a "free -m" on the box, I do not see any increase in memory usage.

In both the cases, I am a bit confused as to where the memory is ending up.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

面犯桃花 2024-08-05 13:54:52

Direct ByteBuffer(使用 ByteBuffer.allocateDirect 分配的)与 MappedByteBuffer 不同,因为它们代表不同的内存部分,并且分配方式也不同。 直接字节缓冲区是一种访问 JVM 外部分配的内存块的方法,通常通过 malloc 调用进行分配(尽管大多数实现可能会使用高效的平板分配器)。 即它只是一个指向内存块的指针。

MappedByteBuffer 表示使用 mmap 调用分配的一段内存,用于执行内存映射 I/O。 因此,MappedByteBuffers 不会像 Direct ByteBuffer 那样注册其内存使用情况。

因此,虽然两者都是“直接”的,因为它们代表 JVM 外部的内存,但它们的目的是不同的。

顺便说一句,为了获取预留内存值,您要反射性地调用 JVM 的内部方法,该方法的实现未包含在任何规范中,因此无法保证该值返回什么。 可以使用 从 JNI 内分配直接 ByteBuffer来自 C/C++ 的 NewDirectByteBuffer 调用(MappedByteBuffers 可能使用此),这可能不会影响预留内存值,该值仅在使用 Java ByteBuffer.allocateDirect 时才可能更改。

Direct ByteBuffers (those allocated using ByteBuffer.allocateDirect) are different to MappedByteBuffers in that they represent different sections of memory and are allocated differently. Direct ByteBuffers are a way to access a block of memory allocated outside of the JVM generally allocated with a malloc call (although most implementations will probably use an efficient slab allocator). I.e. it's just a pointer to a block of memory.

A MappedByteBuffer represents a section of memory allocated using mmap call, which is used to perform memory mapped I/O. Therefore MappedByteBuffers won't register their use of memory in the same way a Direct ByteBuffer will.

So while both are "direct" in that they represent memory outside of the JVM their purposes are different.

As an aside, in order to get the reservedMemory value you are reflectively calling to an internal method of the JVM, whose implementation is not covered by any specification, therefore there are no guarantees as to what that value returns. Direct ByteBuffers can be allocated from within JNI using NewDirectByteBuffer call from C/C++ (MappedByteBuffers likely use this) and this probably doesn't affect the reservedMemory value, which is may only changed when using the Java ByteBuffer.allocateDirect.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文