Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ByteBuffer.allocateDirect()和MappedBytBuffer.load()之间的差异_Java_Unix_Memory_Nio_Bytebuffer - Fatal编程技术网

Java ByteBuffer.allocateDirect()和MappedBytBuffer.load()之间的差异

Java ByteBuffer.allocateDirect()和MappedBytBuffer.load()之间的差异,java,unix,memory,nio,bytebuffer,Java,Unix,Memory,Nio,Bytebuffer,我试图通过使用MappedByteBuffer映射特定文件,在两个或多个JVM之间实现一种共享缓存。从规范中我看到,当我们使用MappedByteBuffer.load()时,它应该将数据加载到直接缓冲区中。我有几个问题要问 我的代码片段:: RandomAccessFile file = new RandomAccessFile("file.txt","rw"); FileChannel fc = file.getChannel(); MappedByteBuffer buf5 = fc.ma

我试图通过使用
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)
{
}
  • 上述代码的输出为0字节,用于直接内存使用(File.txt为1 GB)。但是如果我取消注释这行

    ByteBuffer buf6 = ByteBuffer.allocateDirect(100000000);
    
    我的直接内存使用量为100MB。无法理解为什么会这样,以及为什么我一开始没有得到任何直接内存使用(即,当该行被注释掉时)

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

  • 在这两种情况下,我都有点搞不清楚记忆会在哪里结束

    谢谢

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

    MappedByteBuffer表示使用mmap调用分配的内存部分,该调用用于执行内存映射I/O。因此,MappedByteBuffer不会以直接ByteBuffer相同的方式注册其内存使用

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


    另一方面,为了获得reservedMemory值,您正在反射性地调用JVM的内部方法,而JVM的实现不包含在任何规范中,因此无法保证该值返回什么。可以使用C/C++调用从JNI内部分配直接字节缓冲区(MappedBytebuffer可能会使用此选项),这可能不会影响reservedMemory值,该值仅在使用Java ByteBuffer.allocateDirect时更改。

    感谢您的回复。是的,使用mappedByteBuffer时,保留内存值似乎不受影响。但是,当我映射文件并将其加载到内存中时,我仍然对内存的最终位置感到困惑,因为驻留内存和虚拟内存都增加了,但是linux框中的“free-m”没有显示内存的任何增加。内存映射文件算作虚拟内存,不是物理内存,因此预计虚拟内存使用量会增加。值得注意的是,众所周知,很难确定进程使用了多少物理内存(无论如何,在linux中),因此驻留大小可能包括内存映射,尽管它实际上没有消耗多少物理ram。因此,原因免费不显示任何额外的内存消耗。谢谢Micheal。是的,我认为free在显示框使用情况时不包括内存映射文件/proc/meminfo提供了我想要的信息。