由于HeapByteBuffer和DirectByteBuffer类都是default类型的,所以你无法字节访问到,你只能通过ByteBuffer间接访问到它,因为JVM不想让你访问到它。

分配HeapByteBuffer的方法是:

ByteBuffer.allocate(int capacity);参数大小为字节的数量

分配DirectByteBuffer的方法是:

ByteBuffer.allocateDirect(int capacity);//可以看到分配内存是通过unsafe.allocateMemory()来实现的,这个unsafe默认情况下java代码是没有能力可以调用到的,不过你可以通过反射的手段得到实例进而做操作,当然你需要保证的是程序的稳定性,既然叫unsafe的,就是告诉你这不是安全的,其实并不是不安全,而是交给程序员来操作,它可能会因为程序员的能力而导致不安全,而并非它本身不安全。

1、HeapByteBuffer与DirectByteBuffer,在原理上,前者可以看出分配的buffer是在heap区域的,其实真正flush到远程的时候会先拷贝得到直接内存,再做下一步操作(考虑细节还会到OS级别的内核区直接内存),其实发送静态文件最快速的方法是通过OS级别的send_file,只会经过OS一个内核拷贝,而不会来回拷贝;在NIO的框架下,很多框架会采用DirectByteBuffer来操作,这样分配的内存不再是在java heap上,而是在C heap上,经过性能测试,可以得到非常快速的网络交互,在大量的网络交互下,一般速度会比HeapByteBuffer要快速好几倍。

2、DirectByteBuffer这块区域不是在java heap上,那么这块内存的大小是多少呢?默认是一般是64M,可以通过参数:-XX:MaxDirectMemorySize来控制。

3、直接内存好,我们为啥不都用直接内存?请注意,这个直接内存的释放并不是由你控制的,而是由full gc来控制的,直接内存会自己检测情况而调用system.gc(),但是如果参数中使用了DisableExplicitGC(这个参数作用是禁止代码中显示调用GC),那么如何才能释放直接内存呢?

4、那么full gc不触发,我想自己释放这部分内存有方法吗?可以的,我们看到它的源码中DirectByteBuffer发现有一个:Cleaner,是用来搞资源回收的。DirectByteBuffer类是Default类型的,因此这个类无法直接引用到,是通过反射去找到cleaner的实例,进而调用内部的clean方法,那样做麻烦了,其实并不需要那么麻烦,因为DirectByteBuffer implements了DirectBuffer,而DirectBuffer本身是public的,所以通过接口去调用内部的Clear对象来做clean方法。

下面来做测试来证明这个程序是有效地回收的:

import java.nio.ByteBuffer;
import sun.nio.ch.DirectBuffer; public class DirectByteBufferCleaner { public static void clean(final ByteBuffer byteBuffer) {
if (byteBuffer.isDirect()) {
((DirectBuffer)byteBuffer).cleaner().clean();
}
}
} public static void sleep(long i) {
try {
Thread.sleep(i);
}catch(Exception e) {
/*skip*/
}
}
public static void main(String []args) throws Exception {
ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024 * 100);
System.out.println("start");
sleep(10000);
clean(buffer);
System.out.println("end");
sleep(10000);
}

这里分配了100M内存,为了将结果看清楚,在执行前,执行后分别看看延迟10s,请提前将OS的资源管理器打开,看看当前使用的内存是多少,如果你是linux当然是看看free或者用top等命令来看;本地程序我是用windows完成,在运行前机器的内存如下图所示:

开始运行在输入start后,但是未输出end前,内存直接上升将近100m。

在输入end后发现内存立即降低到2.47m,说明回收是有效的。

此时可以观察JVM堆的内存,不会有太多的变化,注意:JVM本身启动后也有一些内存开销,所以不要将那个开销和这个绑定在一起;这里之所以一次性申请100m也是为了看清楚过程。

HeapByteBuffer和DirectByteBuffer以及回收DirectByteBuffer的更多相关文章

  1. nio DirectByteBuffer如何回收堆外内存

    概述 使用了nio框架的应用,比如服务框架,利用nio建立长连接通信,他们会使用DirectByteBuffer来分配堆外内存,也就是本地直接内存,这个内存的回收不由gc直接维护,我们通常所说的gc, ...

  2. Java堆外内存的使用

    堆外内存的回收见HeapByteBuffer和DirectByteBuffer以及回收DirectByteBuffer 基本类型长度 在Java中有很多的基本类型,比如: byte,一个字节是8位bi ...

  3. HeapByteBuffer与DirectByteBuffer

    HeapByteBuffer,顾名思义,是写在jvm堆上面的一个buffer,底层的本质是一个数组,用类封装维护了很多的索引(limit/position/capacity等) DirectByteB ...

  4. java nio中,HeapByteBuffer与DirectByteBuffer的区别

    HeapByteBuffer,顾名思义,是写在jvm堆上面的一个buffer,底层的本质是一个数组,用类封装维护了很多的索引(limit/position/capacity等) DirectByteB ...

  5. System.gc()和-XX:+DisableExplicitGC启动参数,以及DirectByteBuffer的内存释放

    首先我们修改下JVM的启动参数,重新运行之前博客中的代码.JVM启动参数和测试代码如下: -verbose:gc -XX:+PrintGCDetails -XX:+DisableExplicitGC ...

  6. Netty 内存回收之 noCleaner 策略

    前言 对于堆外内存,使用 System.gc() 是不靠谱的,依赖老年代 FGC 也是不靠谱的,而且大部分调优指南都设置了 -DisableExplicitGC 禁用 System.gc().所以主动 ...

  7. Java NIO浅析

    NIO(Non-blocking I/O,在Java领域,也称为New I/O),是一种同步非阻塞的I/O模型,也是I/O多路复用的基础,已经被越来越多地应用到大型应用服务器,成为解决高并发与大量连接 ...

  8. Java面试总结之AIO与NIO

    1.Java NIO 是一种同步非阻塞的I/O模型 将多个IO的阻塞复用到同一个select的阻塞上,从而使得系统在单线程的情况下处理多个客户端请求. NIO三个核心对象:通道(Channel).缓冲 ...

  9. Java网络编程和NIO详解8:浅析mmap和Direct Buffer

    Java网络编程与NIO详解8:浅析mmap和Direct Buffer 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NI ...

随机推荐

  1. hibernate操作数据库例子

    1.工程目录结构如下 2.引入需要的jar包,如上图. 3.创建持久化类User对应数据库中的user表 package com.hibernate.配置文件.pojo; import java.sq ...

  2. BNU 2418 Ultra-QuickSort (线段树求逆序对)

    题目链接:http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=2418 解题报告:就是给你n个数,然后让你求这个数列的逆序对是多少?题目中n的范围是n & ...

  3. [UOJ#34]多项式乘法

    [UOJ#34]多项式乘法 试题描述 这是一道模板题. 给你两个多项式,请输出乘起来后的多项式. 输入 第一行两个整数 n 和 m,分别表示两个多项式的次数. 第二行 n+1 个整数,分别表示第一个多 ...

  4. Python win7下 django-admin.py startproject mysite命令没有创建mysite?

    解决方案 解决:这个命令在XP下正常(我没试过),我用的win7,无法创建.这属于django的一个bug. 方法是:修改注册表中 HKEY_CLASSES_ROOT/Applications/pyt ...

  5. php获取网页内容方法总结

    抓取到的内容在通过正则表达式做一下过滤就得到了你想要的内容,至于如何用正则表达式过滤,在这里就不做介绍了,有兴趣的,以下就是几种常用的用php抓取网页中的内容的方法. 1.file_get_conte ...

  6. 【SpringMVC】SpringMVC系列4之@RequestParam 映射请求参数值

    4.@RequestParam 映射请求参数值 4.1.概述     Spring MVC 通过分析处理方法的签名,将 HTTP 请求信息绑定到处理方法的相应人参中.Spring MVC 对控制器处理 ...

  7. 44. log(n)求a的n次方[power(a,n)]

    [题目] 实现函数double Power(double base, int exponent),求base的exponent次方,不需要考虑溢出. [分析] 这是一道看起来很简单的问题,很容易写出如 ...

  8. 关于Xcode6 Segue 的疑问,没有解决!

    xcode6 的segue 变化了,如图 关于前3个选项,始终没有太明白,我试验结果如下,简单地把几个viewController连接起来时,无论用show,还是showdetail,还是Presen ...

  9. 用RPM包安装MySQL的默认安装路径问题

    在安装PHP时候要对一些配置选项进行设置,其中就有:--with-mysql[=DIR]:包含MySQL扩展,[=DIR]指定mysql安装目录,省略[=DIR]则为默认位置/usr--with-my ...

  10. excel数据导入SQLite数据库

    参考:http://blog.baisi.net/?110653/viewspace-6725 1.excel表中最上面一行的字段名留着,留着以后导入的时候对应. 2.保存成csv格式,在选择文件类型 ...