java 读写内存_java-读写套接字和文件仅使用本机内存?

Java内存与堆内存交互:套接字传输与零拷贝
博客讨论了Java中套接字传输与系统调用如何涉及本地内存和堆内存,指出JVM实现可能影响数据传输方式。虽然理论上可能实现零拷贝,但实际中由于垃圾收集和性能考虑,OpenJDK11并不支持对堆分配字节缓冲区的零拷贝传输。直接字节缓冲区与NIO结合使用时需注意终结处理,可能导致效率下降。文章建议根据情况权衡复制和垃圾收集的影响,以及使用直接或数组支持的缓冲区。

套接字传输(和系统调用)中的本地内存与堆内存

往返套接字的数据传输只能使用本机(非堆)内存是不正确的.它完全取决于JVM实现,甚至在同一实现中有时可能会有所不同.

实际上,编写直接使用堆内存并避免复制的JNI函数相当容易. JNI API提供了对Java堆中的数据进行零复制访问的方法:

第二个在处理字节数组时非常有用.

与垃圾收集的交互

这些JNI功能为may prevent garbage collection from making progress.通常,进行复制会更有利.在进行阻塞的系统调用时(例如,当不确定知道内核已缓冲要返回的数据时,例如从TCP套接字读取),尤其如此.在其他情况下,有可能以较小的片段逐步处理阵列,以避免长时间的停顿和对副本的需求.

由于这些挑战,即使在内核中不会发生阻塞并且不会对堆产生影响的情况下,OpenJDK 11中的当前实现也不会尝试与堆分配(非直接)字节缓冲区进行零拷贝传输.由于无限制的延迟而进行垃圾收集.

使用直接字节缓冲区的禁忌症

将直接字节缓冲区与NIO一起使用存在不同的问题:这些缓冲区需要某种类型的终结处理.结果,垃圾收集器无法像其他对象一样高效(迅速)处理它们.通常,仅当直接字节缓冲区寿命长(例如,与使用它们的通道一起分配)时,才应谨慎使用.对于临时缓冲区,大多数情况下,由数组支持的缓冲区(或纯数组)是上乘的.

OpenJDK实现通过将直接缓冲区与当前线程相关联,透明地将它们用于通道上的传输,然后将它们返回到每个线程缓存中以备将来使用,从而避免了此问题.这样,直接缓冲区不会不断分配和丢弃.

较旧的OpenJDK版本

上面提到的关键部分数组访问功能可以追溯到Java 1.2.当然,还不确定单个虚拟机和垃圾回收实现是否仍会创建临时副本(对接口进行了精心设计,避免了实现副本无需复制).在OpenJDK 8的Hotspot中,这些JNI函数从不复制,但正如AlekseyShipilёv的文章所述,垃圾收集器的影响因收集器而异.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值