Создание буферов кучи и прямых буферов
allocateDirect(int capacity): выделить новый прямой байтовый буфер. Позиция нового буфера будет равна 0, его границы будут его емкостью, а его метка будет неопределенной. Независимо от того, имеет ли он базовый массив реализации или нет, его метка будет не будь уверен.
allocate(int capacity): выделить новый косвенный байтовый буфер. Позиция нового буфера равна 0, его граница равна его емкости, а его метка не определена. Он будет иметь базовый массив реализации, и его массив будет смещен. Величина сдвига будет быть 0.
Если байтовый буфер является прямым байтовым буфером, JVM попытается выполнить собственные операции ввода-вывода в прямом байтовом буфере, то есть напрямую.пространство ядраДоступ для повышения эффективности работы.Принцип повышения эффективности работы заключается в том, что перед или после каждого вызова операций ввода-вывода на основе операционной системы JVM будет пытаться избежать копирования содержимого буфера в промежуточный буфер или из промежуточный буфер Скопируйте содержимое в область, которая сохраняет шаг.
Затраты времени на выделение и освобождение памяти через буфер, возвращаемый функцией allocateDirect(), обычно выше, чем у непрямого буфера.Данные операции прямого буфера находятся не в куче JVM, а в пространстве ядра, что может быть проанализированы в соответствии с этой структурой По умолчанию прямые буферы хорошо подходят для хранения больших объемов долговременных сохраненных данных, которые восприимчивы к собственным операциям ввода-вывода операционной системы.
Тип буфера, созданный методом allocateDirect(), — DirectByteBuffer, а тип буфера, созданный методом allocate(), — HeapByteBuffer.
При использовании метода allocateDirect() для создания буфера ByteBuffer емкость относится к количеству байтов, а при создании буфера IntBuffer емкость относится к количеству значений int.Если вы хотите преобразовать его в байты, вам нужно умножить емкость на 4. чтобы вычислить общее количество занятых байтов.
Способ освобождения памяти в прямом буфере
- Освободить место вручную
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);
}
}
- Передать в 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 можно запускать несколько раз, порождая несколько процессов, и тогда просмотр использования памяти будет более интуитивным.
Ссылаться на:
- «Техническое руководство по программированию NIO и сокетов»