我正在尝试理解在oracle JVM中运行的strace
Java应用服务器。
我经常看到以下几行:
[pid 10465] 23:04:59.658453 dup2(215, 274) = 274
[pid 10465] 23:04:59.658616 close(274) = 0
在这种情况下,215
是UNIX套接字:
java 10387 XXX 215u unix 0xffff880037962cc0 0t0 153294021 socket
FD 274
是 open TCP套接字。
这些“呼叫对”在多分钟内使用相同的A
套接字重复多次。
我对dup2(A, B)
的理解是它创建了一个文件描述符B
指向/引用同一个文件/套接字A
,如果它仍然打开则首先关闭B
。
dup2()函数应使文件描述符fildes2引用与文件描述符fildes相同的打开文件描述并共享任何锁,并返回fildes2。如果fildes2已经是一个有效的打开文件描述符,它应该先关闭,除非fildes等于fildes2,在这种情况下,dup2()将返回fildes2而不关闭它。
到目前为止,我唯一的猜测是,这是JVM的一种奇怪的,未经优化的行为。不是吗?它有何意义。
如有必要,我会添加更多上下文调用。
答案 0 :(得分:5)
此序列提供了一种关闭套接字的线程安全方法。
dup2
允许在不释放文件描述符的情况下关闭套接字。由于未传输的数据和长的逗留间隔,这可能是一个漫长的操作。 dup2(A, B)
是与
close(B);
fcntl(A, F_DUPFD, B);
即。 B
随时都是有效的描述符。在获取此描述符的所有线程完成未完成的I / O操作之前,保持文件描述符有效至关重要。
fd
被复制(在您的情况下为215)是shutdown
状态的特殊标记套接字。它只创建一次,仅用于通过dup2
关闭其他套接字。
完成dup2
后,原始fd
(274)中的任何读取都将返回EOF,对其进行的任何写入都将出错。
Java为每个文件描述符维护一个使用计数器。线程在获取文件描述符时递增此计数器,并在完成I / O时递减它。
一旦使用计数器降至0,Java就会调用close
来释放文件描述符并使其可供操作系统使用。
Java NIO实现使用相同的技术来关闭文件 虽然我没有看到JDK源代码以外的这种模式。