第12讲 | Java有几种文件拷贝方式?哪一种最高效?
第12讲 | Java有几种文件拷贝方式?哪一种最高效?
讲述:黄洲君
时长12:39大小5.79M
典型回答
考点分析
知识扩展
一课一练
赞 20
提建议
精选留言(56)
- 135767880172018-05-31杨老师,想问一下,一般要几年java经验才能达到看懂你文章的地步??我将近一年经验。。我发现我好几篇都看不懂。。底层完全不懂。。是我太菜了吗。。
作者回复: 非常抱歉,具体哪几篇?公司对一年经验的工程师要求应该也不一样的
共 18 条评论126 - 行者2018-05-31可以利用NIO分散-scatter机制来写入不同buffer。 Code: ByteBuffer header = ByteBuffer.allocate(128); ByteBuffer body = ByteBuffer.allocate(1024); ByteBuffer[] bufferArray = {header, body}; channel.read(bufferArray); 注意:该方法适用于请求头长度固定。展开
作者回复: 赞
共 3 条评论124 - 乘风破浪2018-05-31零拷贝是不是可以理解为内核态空间与磁盘之间的数据传输,不需要再经过用户态空间?
作者回复: 嗯
48 - 夏洛克的救赎2018-05-31请问老师您有参与jdk的开发吗
作者回复: 是的,目前lead的团队主要是QE职责
20 - CC2018-06-07我Nio从没接触过,很难受,两年开发的
作者回复: 不用担心,是理解有难度吗?
16 - 闭门造车2018-06-06你好,我查看jdk8中的源码,看到您说的关于Files.copy其中两种是依靠transferto实现的,但是我翻看源码觉得跟您的理解不同,特来求证,源码如下: public static long copy(Path source, OutputStream out) throws IOException { Objects.requireNonNull(out); try (InputStream in = newInputStream(source)) { return copy(in, out); } } private static long copy(InputStream source, OutputStream sink) throws IOException { long nread = 0L; byte[] buf = new byte[BUFFER_SIZE]; int n; while ((n = source.read(buf)) > 0) { sink.write(buf, 0, n); nread += n; } return nread; }展开共 8 条评论16
- vash_ace2018-06-01其实在初始化 DirectByteBuffer对象时,如果当前堆外内存的条件很苛刻时,会主动调用 System.gc()强制执行FGC。所以一般建议在使用netty时开启XX:+DisableExplicitGC
作者回复: 对,检测不够时会尝试调system.gc,记得老版本有并发分配bug,会出oom;netty,文中提到了,它是hack到内部自己释放...
共 3 条评论15 - mongo2018-05-31杨老师,我也想请教,目前为止您的其他文章都理解的很好,到了上次专栏的NIO我理解的不是很好,今天的这篇可以说懵圈了。到了这一步想突破,应该往哪个方向?我自己感觉是因为基于这两个底层原理的上层应用使用的时候观察的不够深入,对原理反应的现象没有深刻感受,就是所谓还没有摸清楚人家长什么样。所以接下来我会认真在使用基于这些原理实现的上层应用过程中不断深挖和观察,比如认真学习dubbo框架(底层使用到了netty,netty的底层使用了NIO)来帮助我理解NIO。在这个过程中促进对dubbo的掌握,以此良性循环。不知道方向对不对?老师的学习方法是什么?请老师指点避坑。学习方法不对的话时间成本太可怕。展开
作者回复: 我觉得思路不错,结合实践是非常好的;我自身也仅仅是理论上理解,并没有在大规模实践中踩坑,实践中遇到细节的“坑”其实是宝贝,所以你有更多优势;本文从基础角度出发,也是希望对其原理有个整体印象,至少被面试刨根问底时,可以有所准备,毕竟看问题的角度是不同的
13 - 石头狮子2018-05-31若使用非 directbuffer 操作相关 api 的话,jdk 会将其复制为 ditrctbuff。并且在线程内部缓存该directbuffer。jdk 对这个缓存的大小并没有限制。 之前遇到缓存的 directbuffer 过多,导致oom的情况。后续 jdk 版本加入了对该缓存的限制。 额外一点是尽量不要使用堆内的 bytebuffer 操作 channel 类 api。10
- 老陈板2019-02-17本篇文章有恍然大悟的感觉,前面段时间有一家面试问了个这样的问题,我们发现服务器内存使用得特别高,但是堆内存也比较稳定,这种场景是你你会怎么排查?这里就涉及到堆外内存相关的问题!以前不知道有NMT这个工具,然后当时没答好,导致工资少了好多,早点读这篇文章多好。另外注意,sysyem.gc不一定会立即触发fgc,有个权值
作者回复: 一个常见例子是,创建了一堆线程,实际占用内存(RSS)远比堆本身大
8 - 皮蛋2018-11-02杨老师,想问下如果想学操作系统的知识,阅读什么书比较适合,初学者
作者回复: 可以看看《深入理解计算机系统》,如果有精力,再找本linux内核并配合实验,会很有用
8 - Len2018-05-31请教老师: 1. 经常看到 Java 进程的 RES 大小远超过设置的 Xmx,可以认为这就是 Direct Memory 的原因吗?如果是的话,可以简单的用堆实际占用的大小减去 RES 就是 Direct Memory 的大小吗? 2.可以认为 Direct Memory 不论在什么情况下都不会引起 Full GC,Direct Memory 的回收只是在 Full GC (或调用 System.gc())的时候顺带着回收下,是吗?展开
作者回复: 1,一般不是,那东西有个默认大小的,metaspace codecache等等都会占用,后面有章节仔细分析 2,不是,它是利用sun.misc.Cleaner, 实际表现有瑕疵,经常要更依赖system gc去触发引用处理,9和8u有改进,我会有详解
8 - 灰飞灰猪不会灰飞.烟...2018-05-31老师,带缓冲区的io流比nio哪一个性能更好?
作者回复: 嗯,文中提到过,不能一概而论,性能通常是特定场景下的比较才有意义
6 - 天王2019-11-2712 java java有几种文件拷贝方式,1 利用Java.io,FileInputStream和FileOutputStream, 2 nio的transferTo和transferFrom,2比1快的原因,是操作系统分用户态和内核态,先在内核态把文件拷贝到内存,再从内核态拷贝到用户态,多了拷贝的过程和上下文切换,3 拷贝的底层实现 操作系统分内核空间和用户空间,操作系统内核和硬盘驱动等在内核空间,用户态在用户空间,文件读取是先从内核态读取磁盘数据到内核缓存中,再切换到用户态,从内核态空间读取到用户态缓存,nio的transferTo不会经用户态,直接在内核态做相应处理 4 Java Java.nio.files.Files.copy,java标准类库提供的copy方法transferTo,底层是调用了InputStream.transferTo,底层调用了用户态的拷贝方法,5 提高拷贝方法 利用缓存,尽量减少io次数,减少内核态到用户态的切换,减少切换开销,减少不必要的转换过程,比如编解码,序列化和反序列化,6 Buffer NIO为每个数据类型提供了各自的Buffer,ByteBuffer,IntBuffer,FloatBuffer,7 DirectBuffer,java提供了堆内和堆外Buffer(DirectBiffer),MappedByteBuffer,将文件大小直接映射为内存区域,程序访问时直接访问,省去了用户态和内核态的空间转换,java尽量对DirectBuffer仅做本地操作,生命周期内的内存地址不修改,内核可以安全访问,可以更高效,同时减少了堆内对象的维护工作。展开6
- 美国的华莱士2019-03-30国外的这遍文章写的还不错,偏基础的可以参考下: https://www.journaldev.com/861/java-copy-file共 4 条评论5
- Cui2018-05-31Direct Buffer 生命周期内内存地址都不会再发生更改,进而内核可以安全地对其进行访问—这里能提高性能的原因 是因为内存地址不变,没有锁争用吗?能否详细解答下?
作者回复: 我理解不是锁的问题,寻址简单,才好更直接
4 - 灰飞灰猪不会灰飞.烟...2018-05-31杨老师 我刚刚做个项目,上传文件到文件服务器,文件大概10M,经常上传失败。假如我上传的文件改成1M,就没这问题了。不知道什么原因,能提供个思路吗?谢谢
作者回复: 有个建议,工程师在沟通故障时,可以收集下:出错信息;客户端、服务端配置;网络情况,比如是否有代理,等等。 至于思路,能否找到程序异常信息之类,做过哪些尝试将问题缩小范围? 定位问题通常就是个不断缩小范围,排除不可能的过程。
共 2 条评论3 - 罗飞2019-01-10零拷贝,是DMA 数据传输,完全由硬件实现的,内核只是起到控制设置作用,不要误人子弟好么
作者回复: 谢谢,建议搜索下Java DMA或者相关的RDMA; 实时上这是个一直在发展的领域,虽然因为种种原因应用场景有限,最新的API发展如RDMA相关,可以了解下 http://openjdk.java.net/jeps/337
共 4 条评论2 - Quincy2018-08-08老师,我想问下,transferto是怎么实现的零拷贝,而避免了用户态和内核态之间转换的开销共 1 条评论3
- 玲玲爱学习2018-06-28堆外缓存是否与内核缓存是同一个东西?共 1 条评论2