java NIO - DirectBuffer 和 HeapBuffer
问题 :
- DirectBuffer 属于堆外存,那应该还是属于用户内存,而不是内核内存?
- FileChannel 的read(ByteBuffer dst)函数,write(ByteBuffer src)函数中,如果传入的参数是HeapBuffer类型,则会临时申请一块DirectBuffer,进行数据拷贝,而不是直接进行数据传输,这是出于什么原因?
DirectBuffer
Java | native
|
DirectByteBuffer | malloc'd
[ address ] -+-> [ data ]
|
DirectByteBuffer 自身是一个Java对象,在Java堆中;而这个对象中有个long类型字段address,记录着一块调用 malloc() 申请到的native memory。DirectByteBuffer 自身是(Java)堆内的,它背后真正承载数据的buffer是在(Java)堆外——native memory中的。这是 malloc() 分配出来的内存,是用户态的。(来自参考文章R大的回答)
DirectBuffer 和 HeapBuffer
两个都是Buffer ,不同的是前者使用的是堆外内存,后者时候的是 JVM 堆内内存。在使用 FileChannel 读写的时候内部实现就有点不同了。以下是FileChannel使用代码
public static void main(String[] args) throws Exception{
RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel channel = aFile.getChannel();
String newData = "New String to write to file..." + System.currentTimeMillis();
// HeapByteBuffer
ByteBuffer buf = ByteBuffer.allocate(48);
// DirectByteBuffer
ByteBuffer dirctBuf = ByteBuffer.allocateDirect(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
channel.write(buf);
}
}
//读取地址
FileInputStream fis = new FileInputStream("C:\\CloudMusic\\Circadian Eyes - Ferris Wheel.mp3");
//写出地址
FileOutputStream fos = new FileOutputStream("D:\\etc\\cas\\logs\\cas_audit.log");
FileChannel fc = fis.getChannel();
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
//回刷回磁盘
mbb.flip();
fos.flush();
fc.close();
fis.close();
如果上面的代码channel.write传入的参数是HeapBuffer类型,则会临时申请一块DirectBuffer,将HeapBuffer中的数据进行数据拷贝到堆外内存,然后剩下就是对DirectBuffer进行IO操作,为什么直接使用HeapBuffer拷贝数据到内核中,然后进行IO操作呢?这是因为如果要把一个Java里的 byte[] 对象的引用传给native代码,让native代码直接访问数组的内容的话,就必须要保证native代码在访问的时候这个 byte[] 对象不能被移动,也就是要被“pin”(钉)住。而虚拟机的GC 算法会移动对象,导致地址会变化,那么后续就会产生错误。详细的见参考资料R大的回答。 OpenJDK的 sun.nio.ch.IOUtil.write(FileDescriptor fd, ByteBuffer src, long position, NativeDispatcher nd) 的实现。
static int write(FileDescriptor fd, ByteBuffer src, long position,
NativeDispatcher nd)
throws IOException
{
if (src instanceof DirectBuffer)
return writeFromNativeBuffer(fd, src, position, nd); // Substitute a native buffer
int pos = src.position();
int lim = src.limit();
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
try {
bb.put(src);
bb.flip();
// Do not update src until we see how many bytes were written
src.position(pos); int n = writeFromNativeBuffer(fd, bb, position, nd);
if (n > 0) {
// now update src
src.position(pos + n);
}
return n;
} finally {
Util.offerFirstTemporaryDirectBuffer(bb);
}
}
MappedByteBuffer
MappedByteBuffer 是 DirectBuffer 的父类,它的读写性能比HeapByteBuffer要高(不然FileChannel 内部实现中也不会用DirectByteBuffer进行操作)。MappedByteBuffer 内部原理主要和操作系统的虚拟存储有关,更加直接的联系就是页表相关的知识,先阅读以下这篇文章。
补充
关于 Heap memory 和 Native memory的解释,来自stackoverflow
Heap memory: memory within the JVM process that is managed by the JVM to represent Java objects
Native memory/Off-heap: is memory allocated within the processes address space that is not within the heap.
Direct memory: is similar to native, but also implies that an underlying buffer within the hardware is being shared. For example buffer within the network adapter or graphics display. The goal here is to reduce the number of times the same bytes is being copied about in memory.
Finally, depending upon the OS then extra native allocations (assigning of the memory address space) can be carried out via Unsafe alloc and/or by memory mapping a file. Memory mapping a file is especially interesting as it can easily allocate more memory than the machine currently has as physical ram. Also note, that the total address space limit is restricted by the size of a pointer being used, a 32bit pointer cannot go outside of 4GB. Period.
参考资料
- https://www.zhihu.com/question/57374068 (推荐一看)
java NIO - DirectBuffer 和 HeapBuffer的更多相关文章
- 3、谈谈 Java NIO
在 JDK1.4 之后,为了提高 Java IO 的效率,Java 提供了一套 New IO (NIO),之所以称之为 New,原因在于它相对于之前的 IO 类库是新增的.此外,旧的 IO 类库提供的 ...
- Java NIO浅析 转至 美团技术团队
出处: Java NIO浅析 NIO(Non-blocking I/O,在Java领域,也称为New I/O),是一种同步非阻塞的I/O模型,也是I/O多路复用的基础,已经被越来越多地应用到大型应用服 ...
- Java NIO 基础
Java在JDK1.4中引入了 java.nio 类库,为Java进军后端Server和中间件开发打开了方便之门. 一般而言,这里的 nio 代表的是 New I/O,但是从实质上来说,我们可以将其理 ...
- JAVA NIO复习笔记
1. JAVA NIO是什么? 从JDK1.4开始,java提供了一系列改进的输入/输出处理的新功能,这些功能被统称为新IO(New IO,简称NIO),新增了许多用于处理输入/输出的类,这些类都被放 ...
- Java NIO 学习笔记
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/SJQ. http://www.cnblogs.com/shijiaqi1066/p/3344148.html ...
- Java NIO 之 Buffer
Java NIO 之 Buffer Java NIO (Non Blocking IO 或者 New IO)是一种非阻塞IO的实现.NIO通过Channel.Buffer.Selector几个组件的协 ...
- 详解 Java NIO
文件的抽象化表示,字节流以及字符流的文件操作等属于传统 IO 的相关内容,我们已经在前面的文章进行了较为深刻的学习了. 但是传统的 IO 流还是有很多缺陷的,尤其它的阻塞性加上磁盘读写本来就慢,会导致 ...
- 从I/O多路复用到Netty,还要跨过Java NIO包
本文是Netty系列第4篇 上一篇文章我们深入了解了I/O多路复用的三种实现形式,select/poll/epoll. 那Netty是使用哪种实现的I/O多路复用呢?这个问题,得从Java NIO包说 ...
- 源码分析netty服务器创建过程vs java nio服务器创建
1.Java NIO服务端创建 首先,我们通过一个时序图来看下如何创建一个NIO服务端并启动监听,接收多个客户端的连接,进行消息的异步读写. 示例代码(参考文献[2]): import java.io ...
随机推荐
- Oracle允许IP访问配置
http://www.linuxidc.com/Linux/2014-10/108650.htm 1.oracle服务器下/opt/app/oracle/product/11.2.0/network/ ...
- 从原理到方案,一步步讲解web移动端实现自适应等比缩放
前言 在移动端做自适应,我们常用的有媒体查询,rem ,em,宽度百分比这几种方案.但是都各有其缺点. 首先拿媒体查询来说,在某一个宽度区间内只能使用一种样式,为了适应不同屏幕要,css的代码量就会增 ...
- linux上安装git以及使用
用git --version命令检查是否已经安装 在CentOS5的版本,由于yum源中没有git,所以需要预先安装一系列的依赖包.在CentOS6的yum源中已经有git的版本了,可以直接使用yum ...
- os 和shutil模块的使用方法
1.python中对文件.文件夹操作时经常用到的os模块和shutil模块常用方法. 1.得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd() 2.返回指定目录下的所有文件 ...
- 【StarUML】 活动图
StarUML中的活动图本质上是流程图,活动图相对来说,更加专业,它有对信号的处理,对状态动作.数据区别表示,使得更清晰地了解控制流的走向. 1.基本元素 a.活动状态图(Activity).动作状态 ...
- CentOS之service iptables stop 显示not loaded
停止firewalld服务停止防火墙,并禁用这个服务 sudo systemctl stop firewalld.servicesudo systemctl disable firewalld.ser ...
- 【转载】Spring MVC入门
转自:http://www.importnew.com/15141.html MVC框架是什么 模型-视图-控制器(MVC)是一个众所周知的以设计界面应用程序为基础的设计模式.它主要通过分离模型.视图 ...
- 刷题2. Add Two Numbers
一.题目要求 You are given two non-empty linked lists representing two non-negative integers. The digits a ...
- sqlserver 查看视图语句
本人sql小白一个,在项目中遇到了视图的使用,但是不知道视图的语句怎么查看,所以在网上搜索了一下,查到了一下的查看方式,再次记录一下: 方法一->前提: 已经创建好的视图 sp_helptext ...
- 对C#继承、多态的理解
11月3日 阴天 前两天看某位大牛写的程序,对于C#多态有困惑,今天一大早来查阅了不少资料,自认为有了一个基本的认知,记录下来,一扫今天这阴霾的天气 ------------------------- ...