`
wxyfighting
  • 浏览: 191139 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

java之HeapByteBuffer&DirectByteBuffer以及回收DirectByteBuffer

 
阅读更多

byte buffer一般在网络交互过程中java使用得比较多,尤其是以NIO的框架中;

看名字就知道是以字节码作为缓冲的,先buffer一段,然后flush到终端。

而本文要说的一个重点就是HeapByteBuffer与DirectByteBuffer,以及如何合理使用DirectByteBuffer。


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

最基本的情况下

分配HeapByteBuffer的方法是:

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

分配DirectByteBuffer的方法是:

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

由于HeapByteBufferDirectByteBuffer类都是default类型的,所以你无法字节访问到,你只能通过ByteBuffer间接访问到它,因为JVM不想让你访问到它,对了,JVM不想让你访问到它肯定就有它不可告人的秘密;后面我们来跟踪下他的秘密吧。


2、前面说到了,这块区域不是在java heap上,那么这块内存的大小是多少呢?默认是一般是64M,可以通过参数:-XX:MaxDirectMemorySize来控制,你够牛的话,还可以用代码控制,呵呵,这里就不多说了。


3、直接内存好,我们为啥不都用直接内存?请注意,这个直接内存的释放并不是由你控制的,而是由full gc来控制的,直接内存会自己检测情况而调用system.gc(),但是如果参数中使用了DisableExplicitGC那么这是个坑了,所以啊,这玩意,设置不设置都是一个坑坑,所以java的优化有没有绝对的,只有针对实际情况的,针对实际情况需要对系统做一些拆分做不同的优化。


4、那么full gc不触发,我想自己释放这部分内存有方法吗?可以的,在这里没有什么是不可以的,呵呵!私有属性我们都任意玩他,还有什么不可以玩的;我们看看它的源码中DirectByteBuffer发现有一个:Cleaner,貌似是用来搞资源回收的,经过查证,的确是,而且又看到这个对象是sun.misc开头的了,此时既惊喜又郁闷,呵呵,只要我能拿到它,我就能有希望消灭掉了;下面第五步我们来做个试验。


5、因为我们的代码全是私有的,所以我要访问它不能直接访问,我需要通过反射来实现,OK,我知道要调用cleaner()方法来获取它Cleaner对象,进而通过该对象,执行clean方法;(付:以下代码大部分也取自网络上的一篇copy无数次的代码,但是那个代码是有问题的,有问题的部分,我将用红色标识出来,如果没有哪条代码是无法运行的

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();
              }
        }
}

上述类你可以在任何位置建立都可以,这里多谢一楼的回复,以前我的写法是见到DirectByteBuffer类是Default类型的,因此这个类无法直接引用到,是通过反射去找到cleaner的实例,进而调用内部的clean方法,那样做麻烦了,其实并不需要那么麻烦,因为DirectByteBuffer implements了DirectBuffer,而DirectBuffer本身是public的,所以通过接口去调用内部的Clear对象来做clean方法。


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

在任意一个地方写一段main方法来调用,我这里就直接写在这个类里面了:

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也是为了看清楚过程,其余的可以做实验玩玩了。


分享到:
评论

相关推荐

    Java获取CPU&主板&硬盘序列号

    通过Java代码获取PC机的CPU、主板、硬盘序列号

    java servlet & jsp cookbook

    介绍jsp和servlet最经典的书籍之一了,希望对大家有用。。。

    Java垃圾回收机制详解和调优.doc

    Java垃圾回收机制详解和调优.doc Java垃圾回收机制详解和调优.doc Java垃圾回收机制详解和调优.doc Java垃圾回收机制详解和调优.doc Java垃圾回收机制详解和调优.doc Java垃圾回收机制详解和调优.doc Java垃圾回收...

    Java垃圾回收机制总结

    Java垃圾回收机制总结

    java垃圾回收机制简述

    此文档详细介绍了java回收机制的工作原理、工作过程,以及在程序中使用的一些注意事项

    Java常用排序算法&程序员必须掌握的8大排序算法+二分法查找

    Java常用排序算法&程序员必须掌握的8大排序算法+二分法查找 Java常用排序算法&程序员必须掌握的8大排序算法+二分法查找

    基于java NIO的简单聊天软件示例

    NIO是一种基于通道和缓冲区的I/O方式,它可以使用Native函数库直接分配堆外内存(区别于JVM的运行时数据区),然后通过一个存储在java堆里面的DirectByteBuffer对象作为这块内存的直接引用进行操作。这样能在一些...

    JAVA上百实例源码以及开源项目

     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...

    【IT十八掌徐培成】Java基础第26天-07.DirectByteBuffer.zip

    【IT十八掌徐培成】Java基础第26天-07.DirectByteBuffer.zip

    【IT十八掌徐培成】Java基础第26天-08.DirectByteBuffer2.zip

    【IT十八掌徐培成】Java基础第26天-08.DirectByteBuffer2.zip

    [Java] Java 编程面试揭秘 英文版

    Java is a popular and powerful language that is a virtual requirement for businesses making use of IT in their daily operations For Java programmers this reality offers job security and a wealth of ...

    JAVA_API1.6文档(中文)

    java.lang.management 提供管理接口,用于监视和管理 Java 虚拟机以及 Java 虚拟机在其上运行的操作系统。 java.lang.ref 提供了引用对象类,支持在某种程度上与垃圾回收器之间的交互。 java.lang.reflect 提供类...

    java反序列化漏洞利用工具WebLogicExploit

    使用注意: 1. WebLogic反弹需要等5秒左右 2. 该工具为对外测试版,请尽量按照正常思路来用,比如... 体积更小,不再依赖java环境,但程序采用.net编写,需要.net 4.0环境 待完成: weblogic回显结果测试中,稍后加入

    Java 面经手册·小傅哥.pdf

    这是一本以面试题为入口讲解 Java 核心内容的技术书籍,书中内容极力的向你证实代码是对数学逻辑的具体实现。当你仔细阅读书籍时,会发现Java中有大量的数学知识,包括:扰动函数、负载因子、拉链寻址、开放寻址、...

    java源码包---java 源码 大量 实例

     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...

    w3school java & java web教程 飞龙整理 20141001

    w3school java & java web教程 飞龙整理 20141001

    JAVA API官方中文版手册chm文件文档

    JAVA API官方文档中文版软件包 java.applet java.awt java.awt.color java.awt.datatransfer java.awt.dnd java.awt.event java.awt.font java.awt.geom java.awt.im java.awt.im.spi java.awt.image ...

    Java实现MD5加密解密

    Java实现MD5加密以及解密,附带测试类,具体见代码。 Java实现MD5加密以及解密,附带测试类,具体见代码。 Java实现MD5加密以及解密,附带测试类,具体见代码。 Java实现MD5加密以及解密,附带测试类,具体见代码。

    Java 中文入门学习手册合集[chm版]

    第一章 Java语言的产生及其特点 第二章 Java程序开发与运行环境 第三章 Java程序设计基础 第四章 Java应用程序的基本框架 第五章 Java的类 第六章 Java图形用户接口 第七章 多线程 第八章 Java的"异常" 第九...

Global site tag (gtag.js) - Google Analytics