当前位置:  开发笔记 > 编程语言 > 正文

缓冲区与不安全区 - 外部JVM

如何解决《缓冲区与不安全区-外部JVM》经验,为你挑选了1个好方法。

我要求在GC无法控制的可用RAM中使用空格.我读了几篇同样的文章,介绍了两种方法.它们在以下代码中指定.

package com.directmemory;

import java.lang.reflect.Field; import java.nio.ByteBuffer;

import sun.misc.Unsafe;

公共类DirectMemoryTest {

public static void main(String[] args) {

    //Approach 1
    ByteBuffer directByteBuffer = ByteBuffer.allocateDirect(8);
    directByteBuffer.putDouble(1.0);
    directByteBuffer.flip();
    System.out.println(directByteBuffer.getDouble());

    //Approach 2
    Unsafe unsafe = getUnsafe();
    long pointer = unsafe.allocateMemory(8);
    unsafe.putDouble(pointer, 2.0);
    unsafe.putDouble(pointer+8, 3.0);

    System.out.println(unsafe.getDouble(pointer));
    System.out.println(unsafe.getDouble(pointer+8));
    System.out.println(unsafe.getDouble(pointer+16));
}

public static Unsafe getUnsafe() {
    try {
        Field f = Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        return (Unsafe) f.get(null);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

}

我有一些问题

1)为什么我应该注意代码中提到的方法1,因为根据我的理解,ByteBuffer.allocateDirect()不能返回一个存储容量大于2GB的缓冲区?因此,如果我的要求是存储3 GB的数据,我必须创建一个新的缓冲区并将数据存储在那里,这意味着除了存储数据之外,我还有额外的责任来识别相应的缓冲区(在'n列表中) 'buffers),它维护一个指向直接内存的指针.

2)不是方法2比方法1快一点,因为我不必首先找到缓冲区然后找到数据,我只需要一个对象字段的索引机制并使用getDouble/getInt方法并传递绝对值地址 ?

3)与PID相关的直接内存分配(关于堆内存吗?)?如果在一台机器上,我有2个java进程,在PID 1中的allocateMemory调用和PID 2给我永远不会交叉使用的内存块?

4)为什么最后一个sysout语句没有导致0.0?这个想法是每个double使用8个字节,所以我在allocateMemory返回的地址处存储1.0,表示地址= 1,地址1 + 8处的2.0为9,然后停止.那么默认值不应该是0.0吗?



1> Thomas Kläge..:

需要考虑的一点是sun.misc.Unsafe不是受支持的API.它将被其他东西取代(http://openjdk.java.net/jeps/260)

1)如果您的代码必须在Java 8到Java 10(及更高版本)中保持不变,那么使用ByteBuffers方法1就是可行的方法.

如果您已准备好使用sun.misc.Unsafe替换Java 9/Java 10中的任何替换,您可以使用sun.misc.Unsafe.

2)对于超过2 GBytes方法的非常大的数据结构,由于方法1中必要的额外间接,2可能更快.但是如果没有可靠的(微)基准测试,我就不会在其上下注任何东西.

3)分配的内存始终绑定到当前运行的JVM.因此,如果两台JVM在同一台机器上运行,您将无法获得相交的内存.

4)您正在分配8个字节的未初始化内存.您现在可以合法访问的唯一内存量是8个字节.对于超出分配大小的内存,不做任何保证.

4A)你正在编写超出你分配的内存8个字节(unsafe.putDouble(pointer+8, 3.0);),它已经导致了内存损坏,并可能导致一个JVM崩溃的下一个内存分配.

4b)您正在读取超出分配内存的16个字节,这取决于您的处理器体系结构和操作系统以及之前的内存使用情况,可能导致JVM立即崩溃.

推荐阅读
yzh148448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有