【杂谈】Java I/O的底层实现
前言
Java I/O功能封装的很好,使用起来很方便,就是刚开始学的时候,如果不了解装饰器模式,会被他繁多的类给吓到。用多了也就习惯了,而且现在有很多实用的封装良好的实用类,可直接读写整个文件。开发者不知道底层实现细节,也可以灵活使用,这是封装的一大优点。但是,作为一名软件开发人员,对其所使用的代码不能仅仅停留在熟悉功能特性上,最好对其实现原理也要有一定了解。
注:本文引用了部分外文内容,并根据自己的理解进行了翻译,连接将在文末贴出。
缓冲处理、内核空间vs用户空间
--------------------------------------外文引用内容Begin(已翻译)----------------------------------------------------------------
缓冲,以及如何处理缓冲是所有IO的基本内容。术语"I/O"(输入输出)指的不过就是从缓冲区移入或移除数据。通常,进程执行I/O操作的方式是,向操作系统发送请求,请求其填充自己的缓冲区(或者把自己缓冲区的内容写出)。这就是I/O这个概念的全部内容。要实现这些传输操作,操作系统底层的实现非常复杂。但是在概念上,本文所要讲述的内容则非常直白。

注意:User space和Kernel space 都属于内存。内存分为两个区,用户区和系统区(内核区)。
上图简要展示了,块数据如何从外部源头(比如硬盘)移入到进程的内存空间的过程。首先,这个进程通过系统调用read(),请求填充自己的缓冲区。这将导致内核发送一个命令到磁盘控制器,使其从磁盘中抓取数据。磁盘控制器通过DMA把数据直接写入到内核空间缓冲区,这个过程不需要CPU干预。一旦磁盘控制器完成了填充数据的任务,内核就将数据从内核空间的临时缓冲区转移到进程指定的缓冲区内。
有一件事需要注意,内核会试图缓冲或者说预加载一些数据,所以有可能进程所请求的数据已经在内核空间里了。如果这样的话,进程请求的数据,只需要从内核缓冲区拷贝一份即可。如果数据不在内核空间内,则在内核获取数据到内存的过程中,此进程将被挂起。
--------------------------------------外文引用内容End(已翻译)-------------------------------------------------------------------
从上述内容可知:
- Java的读写操作,底层由C/C++实现。而不是直接与OS接触
- C/C++读写操作,需要OS服务
- 内核自带缓冲,会过分加载
- 如果内存中没有数据的缓冲,读写操作将阻塞当前线程(OS会帮你挂起线程)
DMA
DMA(Direct Memory Access,直接内存存取)是I/O设备控制方式的一种。我个人认为它们的主要差别在于CPU的参与I/O控制的程度
I/O设备控制方式有:
- 程序I/O方式——CPU需反复检查
- 中断I/O方式——每完成一个字节的读写,通知CPU
- DMA方式——每完成一个块(多字节)的读写,通知CPU
- I/O通道方式(暂不了解)
在DMA读写I/O设备的时候,CPU不会被影响,它可以继续执行。注意!这里能继续执行,指的是CPU可以继续运行,而此I/O操作的线程已经被挂起,不参与CPU调度。I/O操作完成后,该线程才被唤醒,参与调度(加入就绪队列,等待时间片)
系统调用
系统调用是应用程序间接调用OS函数的方式。C语言有提供与系统调用相对应的库函数。这里就是read、write。
BufferedXXStream
注意,对于Java来说,系统调用的开销是比较大的。首先读写操作要触发的是本地方法read0,readBytes,write0,writeBytes,这里JNI需要一定开销。还有就是每产生一个系统调用,就可能产生上千个机器指令,这种开销是不容小觑的。所以,我们要尝试减少系统调用。那有人就会问了,不行啊,我数据又不能缺斤少两,少读少写肯定出问题,怎么减少调用?这不是很好解决吗,每次多读写一点,调用的次数不就少了嘛。而BufferedXXStream就是这么用的,例如,BufferedInputStream的read无参方法只读取一个字节,而实际上BufferedInputStream默认读取了8kb,这些数据用字节数组保留。
对了,如果对上图,不是很理解,可以看看这张。
即运行时,有一个对象BufferedInputStream,其调用一次read()方法,数据保留到buf数组中。

参考文献
How Java I/O Works Internally at Lower Level?(外网)
【杂谈】Java I/O的底层实现的更多相关文章
- 如何精确地测量java对象的大小-底层instrument API
转载: 如何精确地测量java对象的大小-底层instrument API 关于java对象的大小测量,网上有很多例子,大多数是申请一个对象后开始做GC,后对比前后的大小,不过这样,虽然说这样测量对象 ...
- Java进阶(二十五)Java连接mysql数据库(底层实现)
Java进阶(二十五)Java连接mysql数据库(底层实现) 前言 很长时间没有系统的使用java做项目了.现在需要使用java完成一个实验,其中涉及到java连接数据库.让自己来写,记忆中已无从搜 ...
- 《Java并发编程的艺术》Java并发机制的底层实现原理(二)
Java并发机制的底层实现原理 1.volatile volatile相当于轻量级的synchronized,在并发编程中保证数据的可见性,使用 valotile 修饰的变量,其内存模型会增加一个 L ...
- 【java并发编程艺术学习】(三)第二章 java并发机制的底层实现原理 学习记录(一) volatile
章节介绍 这一章节主要学习java并发机制的底层实现原理.主要学习volatile.synchronized和原子操作的实现原理.Java中的大部分容器和框架都依赖于此. Java代码 ==经过编译= ...
- Java 并发系列之二:java 并发机制的底层实现原理
1. 处理器实现原子操作 2. volatile /** 补充: 主要作用:内存可见性,是变量在多个线程中可见,修饰变量,解决一写多读的问题. 轻量级的synchronized,不会造成阻塞.性能比s ...
- Java并发机制的底层实现原理之volatile应用,初学者误看!
volatile的介绍: Java代码在编译后会变成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现 ...
- java常用集合框架底层实现简介与注意点
Collection: ArrayList:1:底层实现是数组,默认长度是10.2:add(),判断是否数组越界,是数组扩容为原来的两倍.3:remove(),copy数组,size-1,释放空虚的空 ...
- 再学Java 之 HashMap的底层实现
今天参加欢聚时代的面试,我说我自己依靠自己的理解重新实现过HashMap.描述我自己的实现思想后,面试官问“hashmap”底层如果用数组不是效率比较低吗,不是更应该用红黑树吗?我一下子就蒙了.用数组 ...
- JAVA框架 Spring AOP底层原理
一:AOP(Aspect Oriented Programming)面向切面编程. 底层实现原理是java的动态代理:1.jdk的动态代理.2.spring的cglib代理. jdk的动态代理需要被代 ...
随机推荐
- (数论)LightOJ -- 1245
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=98634#problem/B(acm14) Description I was tryin ...
- java基础-day30
第07天 MySQL数据库 今日内容介绍 u 多表关系实战练习 u 多表查询 u SQL语句的练习 第1章 多表关系实战练习 1.1 多表关系--实战1--省和市 1.1.1 需求分析 在数据库 ...
- PAT甲级 1126. Eulerian Path (25)
1126. Eulerian Path (25) 时间限制 300 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue In grap ...
- user_agent
public function getipinfo($ip) { $res = '其他'; $url = "http://int.dpool.sina.com.cn/iplookup/ipl ...
- Hadoop-1.2.1伪分布下 hive-0.10.0内嵌模式安装
Hadoop-1.2.1伪分布下 hive-0.10.0内嵌模式安装 1.下载hive-0.10.0 网址是:http://archive.apache.org/dist/hive/hive-0.10 ...
- Git之初识
我的Github地址:https://github.com/shinianzongjishinianxin 初见总是美好的,可是我第一次看到github有点纠结,因为看不懂,然而最终半蒙半猜还是注册完 ...
- 新建WebAPI项目时遇到的问题
1 处理程序“ExtensionlessUrlHandler-Integrated-4.0”在其模块列表中有一个错误模块“ManagedPipelineHandler” 以管理员运行下面的命令注册 ...
- VS2017+EF+Mysql生成实体数据模型(解决闪退的坑) 版本对应才行
最近要使用VS2017+EF+Mysql,在生成实体数据模型踏过一些坑,在此做个总结. 1.先下载并安装 mysql-connector-net-6.9.10.msi 和 mysql-for-vi ...
- [R]关于R语言的绘图函数
1. 首先就是plot(x,y,...) 参数: x: 所绘图形横坐标构成的对象 y: 所绘图形纵坐标构成的对象 type: 指定所绘图形类型 pch: 指定绘制点时使用的符号 cex: 指定符号的大 ...
- MariaDB 用户与权限管理(12)
MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可MariaDB的目的是完全兼容MySQL,包括API和命令行,MySQL由于现在闭源了,而能轻松成为MySQ ...