我需要使用 GC 无法控制的可用 RAM 中的空间。我读了几篇关于这方面的文章,其中介绍了两种方法。它们在以下代码中指定。
package com.directmemory;
导入java.lang.reflect.Field; 导入 java.nio.ByteBuffer;
导入 sun.misc.Unsafe;
公共(public)类 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 和 PID 2 中的 allocateMemory 调用让我永远不会使用相交的内存块?
4) 为什么最后一个 sysout 语句的结果不是 0.0?这个想法是每个 double 使用 8 个字节,所以我将 1.0 存储在 allocateMemory 返回的地址处,比如地址 = 1,地址 1+8 处的 2.0 即 9,然后停止。那么默认值不应该是 0.0 吗?
最佳答案
需要考虑的一点是 sun.misc.Unsafe 不是受支持的 API。它将被其他东西取代 ( http://openjdk.java.net/jeps/260 )
1) 如果您的代码必须在 Java 8 到 Java 10(及更高版本)中不加改动地运行,则使用 ByteBuffers 的方法 1 是可行的方法。
如果您准备好用 Java 9/Java 10 中的任何替换替换 sun.misc.Unsafe 的使用,您可能会选择 sun.misc.Unsafe。
2) 对于超过 2 GB 的非常大的数据结构,方法 2 可能更快,因为方法 1 中需要额外的间接寻址。但是,如果没有可靠的(微观)基准,我不会在上面打赌。
3) 分配的内存总是绑定(bind)到当前运行的JVM。因此,如果两个 JVM 在同一台机器上运行,您将不会获得交叉内存。
4) 您正在分配 8 个字节的未初始化 内存。您现在可以合法访问的唯一内存量是 8 个字节。对于超出您分配的大小的内存,我们不作任何保证。
4a) 您正在写入超出分配内存的 8 个字节 (unsafe.putDouble(pointer+8, 3.0);
),这已经导致内存损坏并可能导致 JVM 崩溃下一次内存分配。
4b) 您正在读取超过分配内存的 16 个字节,这(取决于您的处理器架构和操作系统以及之前的内存使用情况)可能会导致 JVM 立即崩溃。
关于java - Buffer 与 Unsafe - 在 JVM 之外,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34469568/