堆内存在jvm的内存范围之内,系统进行io操作时会将数据区域拷贝一份到os的内存区域(系统内存空间),零拷贝实质就是省略了从jvm内存复制到系统的内存缓冲区的步骤。
1.为什么系统进行io操作时必须将数据区域拷贝一份到os的内存区域?
因为jvm会对它所管理的内存区域进行gc回收,或者内存地址移动,可能会对这块内存的数据进行更改,根据我们的假设,由于这块区域os也在使用,jvm对这块共享数据发生了变更,os那边就会出现数据错乱的情况。
2.可以在io过程中锁定对象地址吗?
如果要把一个Java里的 byte[] 对象的引用传给native代码,让native代码直接访问数组的内容的话,就必须要保证native代码在访问的时候这个 byte[] 对象不能被移动,也就是要被“pin”(钉)住。
可惜HotSpot VM出于一些取舍而决定不实现单个对象层面的object pinning,要pin的话就得暂时禁用GC——也就等于把整个Java堆都给pin住。HotSpot VM对JNI的Critical系API就是这样实现的。这用起来就不那么顺手。