Java使用堆外内存 - ZhangTory's NoteBlog - 张耀誉的笔记博客

Java使用堆外内存

为什么要使用堆外内存?一般来说JVM内存有限且远小于物理内存,使用堆外内存可以直接利用物理内存。此外,堆内内存是可以用JVM工具直接dump出来的,而堆外内存的数据不能直接dump出来。

使用ByteBuffer开辟对外内存

在java中可以使用nio下的ByteBuffer简单的开辟对外内存。
根据堆外内存的特性,比如我们想把密码保存在内存,同时还不想密码被JVM工具dump出来,那我们可以实现代码:

public class PasswordStore {
    
    private static final ByteBuffer PASSWORD_BUFFER = ByteBuffer.allocateDirect(1024);
    
    public static synchronized byte[] getPassword() {
        PASSWORD_BUFFER.flip();
        int size = PASSWORD_BUFFER.limit();
        if (size == 0) {
            return null;
        }
        byte[] password = new byte[size];
        PASSWORD_BUFFER.get(password);
        return password;
    }

    public static synchronized void setPassword(char[] password) {
        PASSWORD_BUFFER.clear();
        for (char c : password) {
            PASSWORD_BUFFER.put((byte) c);
        }
    }

}

并发安全的坑

注意上面的代码我加上了synchronized,是因为在并发时可能出现安全问题,比如两个线程出现如下交替执行时:

PASSWORD_BUFFER.flip(); // Thread 1
int size = PASSWORD_BUFFER.limit(); // Thread 1
PASSWORD_BUFFER.flip(); // Thread 2

// Thread 1
byte[] password = new byte[size];
PASSWORD_BUFFER.get(password); // java.nio.BufferUnderflowException

当线程2的flip方法插入在线程1的limit和get方法之间时,线程1在get时就会抛出异常BufferUnderflowException。

添加新评论

电子邮件地址不会被公开,评论内容可能需要管理员审核后显示。