使用sun.misc.Unsafe获取Java数组项的地址?

时间:2011-10-28 20:50:08

标签: java pointers memory native unsafe

我正在努力理解sun.misc.Unsafe的文档 - 我想因为它不适合一般用途,没有人真的为让它变得可读而烦恼 - 但实际上我真的需要一种方法来查找地址数组中的元素(以便我可以将指针传递给本机代码)。有没有人有任何工作代码这样做?它可靠吗?

3 个答案:

答案 0 :(得分:6)

这是一份工作样本。但是请小心,因为您可能会因为Unsafe类的不当使用而轻易导致JVM崩溃。

import java.lang.reflect.Field;

import sun.misc.Unsafe;

public class UnsafeTest {

    public static void main(String... args) {
        Unsafe unsafe = null;

        try {
            Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            unsafe = (sun.misc.Unsafe) field.get(null);
        } catch (Exception e) {
            throw new AssertionError(e);
        }

        int ten = 10;
        byte size = 1;
        long mem = unsafe.allocateMemory(size);
        unsafe.putAddress(mem, ten);
        long readValue = unsafe.getAddress(mem);
        System.out.println("Val: " + readValue);

    }
}

答案 1 :(得分:6)

您可以使用ByteBuffer.allocateDirect()直接缓冲区,而不是使用数组。它具有字段中的地址,并且该地址在ByteBuffer的生命周期内不会改变。直接ByteBuffer使用最小的堆空间。您可以使用反射获取地址。


您可以使用Unsafe获取地址,问题是GC可以随时移动它。对象没有在内存中修复。

在JNI中,您可以使用特殊方法将数据复制到Java对象或从Java对象复制数据以避免此问题(以及其他问题)如果您想在具有C代码的对象之间交换数据,我建议您使用这些方法。

答案 2 :(得分:1)

为什么呢? JNI中有很多用于处理Java数组内容的工具。您不需要使用下周可能不存在的未记录的内部Sun类。