NIO直接缓冲区释放内存的方法

建立堆缓冲区与直接缓冲区

allocateDirect(int capacity): 分配新的直接字节缓冲区.新的缓冲区的位置将为0,其界限为其容量,其标记是不肯定的.不管它是否具备底层实现数组,其标记都是不肯定的.java

allocate(int capacity): 分配一个新的非直接字节缓冲区.新缓冲区的位置为0,其界限为其容量,其标记是不肯定的.它将具备一个底层实现数组,且其数组偏移量将为0.编程

若是字节缓冲区为直接字节缓冲区,则JVM会尽可能在直接字节缓冲区上执行本机I/O操做,也就是直接对内核空间进行访问,以提升运行效率.提升运行效率的原理就是在每次调用基于操做系统地I/O操做以前或以后,JVM都会尽可能避免将缓冲区的内容复制到中间缓冲区中,或者从中间缓冲区中复制内容,这样就节省了一个步骤.数组

经过allocateDirect()返回的缓冲区进行内存的分配和释放所需的时间成本一般高于非直接缓冲区.直接缓冲区操做的数据不在JVM堆中,而是在内核空间中,根据这个结构能够分析出,直接缓冲区善于保存那些易受操做系统本机I/O操做影响的大量、长时间保存到的数据。bash

使用allocateDirect()方法建立出来的缓冲区类型为DirectByteBuffer,使用allocate()方法建立出来的缓冲区类型为HeapByteBuffer.ui

使用allocateDirect()方法建立ByteBuffer缓冲区时,capacity指的是字节的个数,而建立IntBuffer缓冲区时,capacity指的是int值得数目,若是要转换成字节,则capacity要乘以4,来算出占用的总字节数。spa

直接缓冲区释放内存的方法

  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类能够运行屡次,产生多个进程,而后再查看内存使用状况会更加直观.操作系统

参考:code

  1. 《NIO与Socket编程技术指南》
相关文章
相关标签/搜索