由于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. CSS2-3常见的demo列子总结

    CSS2-3常见的demo列子总结 阅读目录 1. css超过一行或者多行后显示省略号. 2. css图片未知高度垂直居中完美解决方案. 3. 学习使用 :before和 :after伪元素 回到顶部 ...

  2. 老项目的#iPhone6与iPhone6Plus适配#iOS8无法开启定位问题和#解决方案#

    本文永久地址为 http://www.cnblogs.com/ChenYilong/p/4020359.html,转载请注明出处. iOS8的定位和推送的访问都发生了变化, 下面是iOS7和iOS8申 ...

  3. 繁华模拟赛 David与Vincent的博弈游戏

    #include<iostream> #include<cstdio> #include<string> #include<cstring> #incl ...

  4. 《CMake实践》第三部分的示例代码的错误

    <CMake实践>的第三章,初试cmake - cmake的helloworld 中的 PROJECT (HELLO) SET(SRC_LIST main.c) MESSAGE(statu ...

  5. [Effective JavaScript 笔记]第53条:保持一致的约定

    对于api使用者来说,你所使用的命名和函数签名是最能产生普遍影响的决策.这些约定很重要具有巨大的影响力.它建立了基本的词汇和使用它们的应用程序的惯用法.库的使用者必须学会阅读和使用这些.一致的约定可以 ...

  6. 5款Linux最佳照片管理软件

    在谈到 Linux 中的应用程序时,对于不同的用户.不同的使用场景以及不同的使用习惯,在同一类应用当中,总会有多种软件可供选择和备选.就 Linux 中的照片管理软件来说,相信此前的 Google P ...

  7. xcode Git

    http://blog.csdn.net/w13770269691/article/details/38704941 在已有的git库中搭建新库,并且将本地的git仓库,上传到远程服务器的git库中, ...

  8. linux rsync +inotify 实现 实时同步

    前言:     rsync可以实现触发式的文件同步,但是通过crontab守护进程方式进行触发,同步的数据和实际数据会有差异,而inotify可以监控文件系统的各种变化,当文件有任何变动时,就触发rs ...

  9. Java--读写文件综合

    package javatest; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream ...

  10. iOS 用protocol 和 用继承小体会

    最近写程序时,2个类都有相同的函数,又因为在用oc,所以就用了protocol来实现.后来发现其实这2个类除了相同的函数,还需要一些相同的变量,当初用继承的话会更简单.