Метод прямого буфера NIO для освобождения памяти

Java

Создание буферов кучи и прямых буферов

allocateDirect(int capacity): выделить новый прямой байтовый буфер. Позиция нового буфера будет равна 0, его границы будут его емкостью, а его метка будет неопределенной. Независимо от того, имеет ли он базовый массив реализации или нет, его метка будет не будь уверен.

allocate(int capacity): выделить новый косвенный байтовый буфер. Позиция нового буфера равна 0, его граница равна его емкости, а его метка не определена. Он будет иметь базовый массив реализации, и его массив будет смещен. Величина сдвига будет быть 0.

Если байтовый буфер является прямым байтовым буфером, JVM попытается выполнить собственные операции ввода-вывода в прямом байтовом буфере, то есть напрямую.пространство ядраДоступ для повышения эффективности работы.Принцип повышения эффективности работы заключается в том, что перед или после каждого вызова операций ввода-вывода на основе операционной системы JVM будет пытаться избежать копирования содержимого буфера в промежуточный буфер или из промежуточный буфер Скопируйте содержимое в область, которая сохраняет шаг.

Затраты времени на выделение и освобождение памяти через буфер, возвращаемый функцией allocateDirect(), обычно выше, чем у непрямого буфера.Данные операции прямого буфера находятся не в куче JVM, а в пространстве ядра, что может быть проанализированы в соответствии с этой структурой По умолчанию прямые буферы хорошо подходят для хранения больших объемов долговременных сохраненных данных, которые восприимчивы к собственным операциям ввода-вывода операционной системы.

Тип буфера, созданный методом allocateDirect(), — DirectByteBuffer, а тип буфера, созданный методом allocate(), — HeapByteBuffer.

При использовании метода allocateDirect() для создания буфера ByteBuffer емкость относится к количеству байтов, а при создании буфера IntBuffer емкость относится к количеству значений int.Если вы хотите преобразовать его в байты, вам нужно умножить емкость на 4. чтобы вычислить общее количество занятых байтов.

Способ освобождения памяти в прямом буфере

  1. Освободить место вручную
package me.qianlv;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;

/**
 * @author xiaoshu
 * 直接缓冲区释放内存方法
 * 1. 手动释放
 * 2. 交给JVM处理
 * <p>
 * 此程序运行的效果就是1秒钟之后立即回收内存
 * 也就是回收"直接缓冲区"所占用的内存
 */
public class Test9 {
    public static void main(String[] args) throws InterruptedException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        System.out.println("A");
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(Integer.MAX_VALUE);
        System.out.println("B");
        byte[] byteArray = new byte[]{1};
        System.out.println(Integer.MAX_VALUE);
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            byteBuffer.put(byteArray);
        }
        System.out.println("put end.");
        TimeUnit.SECONDS.sleep(1);
        Method cleanerMethod = byteBuffer.getClass().getMethod("cleaner");
        cleanerMethod.setAccessible(true);
        Object returnValue = cleanerMethod.invoke(byteBuffer);
        Method cleanMethod = returnValue.getClass().getMethod("clean");
        cleanMethod.setAccessible(true);
        cleanMethod.invoke(returnValue);
    }
}
  1. Передать в JVM для обработки
package me.qianlv;

import java.nio.ByteBuffer;

/**
 * @author xiaoshu
 * 直接缓冲区释放内存方法
 * 1. 手动释放
 * 2. 交给JVM处理
 * <p>
 * 此程序多次运行后,一直在耗费内存
 * 进程结束后,也不会马上回收内存
 * 而是会在某个时机触发GC垃圾回收器进行内存回收
 */
public class Test10 {
    public static void main(String[] args) {
        System.out.println("A");
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(Integer.MAX_VALUE);
        System.out.println("B");
        byte[] byteArray = new byte[]{1};
        System.out.println(Integer.MAX_VALUE);
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            byteBuffer.put(byteArray);
        }
        System.out.println("put end.");
    }
}

Этот класс *.java можно запускать несколько раз, порождая несколько процессов, и тогда просмотр использования памяти будет более интуитивным.

Ссылаться на:

  1. «Техническое руководство по программированию NIO и сокетов»