最近一段时间都在啃Linux内核, 也给了自己机会再度深入理解Java的NIO实现,希望能获得更多东西,尝试理解以前未能理解的,会涉及少量OpenJDK源码。
因为NIO本身的实现很多牵扯到操作系统,所以需要先稍微过一下,有理解不对的地方,请指出。
1、涉及的Linux知识
1.1、文件描述符
对于Linux来说,一切皆为文件,设备文件、IO文件还是普通文件,都可以通过一个叫做文件描述符(FileDescriptor)的东西来进行操作,其涉及的数据结构可以自行了解VFS。
1.1.1、设备阻塞与非阻塞
任意对设备的操作都是默认为阻塞的,如果没有或有不可操作的资源,会被添加到wait_queue_head_t
中进行等待,直到被semaphore
通知允许执行。此时可以通过fcntl()
函数将文件描述符设置为非阻塞,若没有或有不可操作的资源,立即返回错误信息。
1.2、JVM内存结构 & 虚拟地址空间
众所周知,Linux下的每一进程都有自己的虚拟内存地址,而JVM也是一个进程,且JVM有自己的内存结构。既然如此,两者之间必有对应关系,OracleJDK7提供了NMT,用jcmd pid VM.native_memory detail
可以查看各类区域的reserved,被committed的内存大小及其地址区间,再通过pmap -p
可以看到进程内存信息。
肉眼对比地址区间可以发现,JVM heap是通过mmap分配内存的,位于进程的映射区内,而进程堆区可以被malloc进行分配,对应关系如图。