使用sun.misc.Unsafe处理16位字符

时间:2013-05-23 20:23:54

标签: java memory-management unsafe

帮助我理解一些事情。

使用.. import sun.misc.Unsafe;

如果我需要将一个字符0-127放到某个内存地址,为了防止超出范围的字符,我这样做

if (0 != (c & 0xFF80)) {
    throw new RuntimeException("Only Ascii characters are supported. 0-127.");
} else {
    // Since Java's chars are 16 bits long, i cast it 
    // to byte (8 bits) and then `putByte()`
    UNSAFE.putByte(address, (byte) c);
}

当我的测试检查该内存中的内容时

    char c1 = Ascii.a;
    asciiEncoder.encode(address, c1);
    assertThat(unsafe.getChar(address), is(c1));

此测试似乎在某些机器上通过并失败。 让我再说一遍 - 这适用于某些MAC而不是其他MAC和某些Windows,而不是其他。

什么失败了?返回与'a'不同的字符。

据我所知,如果在分配时,内存没有被清理,但这不是可以解决这个问题吗?

@Before
public void setUp() {
    address = unsafe.allocateMemory(64); // Isn't this mem clean?
} 

如果我将其更改为8位,则测试通过

@Before
public void setUp() {
    address = unsafe.allocateMemory(8);
} 

请帮助我理解

1 个答案:

答案 0 :(得分:2)

Unsafe#allocationMemory的JavaDoc说:

分配给定大小的新的本机内存块(以字节为单位)。的的 内存的内容未初始化;他们通常会 垃圾即可。生成的本机指针永远不会为零,并且将是 对齐所有值类型。通过调用#freeMemory来处理这个内存,或者用#reallocateMemory调整它的大小。

这意味着当您将byte放在那里并阅读char时,您会获得额外的垃圾字节。