Mac OS でこの JDK バグを調査しているときに、理解できないシステム コール トレース出力に出くわしました。
Mac OS X で「java.net.SocketException Invalid argument」が原因で Tomcat の起動に失敗する
短いバージョン: Mac OS では、JDK はselect()
の代わりに を使用しpoll()
ます。そのため、1024 を超えるファイル記述子が割り当てられている場合、select()
呼び出しがNET_Timeout
失敗し、「引数が無効です」というメッセージとともに SocketException が発生すると推測しました。しかし、システム コールを追跡したところ、select()
システム コールや、失敗して EINVAL を設定する呼び出しの形跡は見られなかったので、それが潜在的な原因であるとは考えませんでした。
また、作成した縮小されたテスト ケースの呼び出しも表示されず、問題を理解しました。
import java.io.*;
import java.net.*;
public class SelectTest {
public static void main(String[] args) throws Exception {
for(int i = 0; i < 1024; i++) {
new FileInputStream("/dev/null");
}
ServerSocket socket = new ServerSocket(8080);
socket.accept();
}
}
JDK 1.7u5 以降を使用する Mac OS では、次の例外が発生します。
Exception in thread "main" java.net.SocketException: Invalid argument
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398)
at java.net.ServerSocket.implAccept(ServerSocket.java:522)
at java.net.ServerSocket.accept(ServerSocket.java:490)
at SelectTest.main(SelectTest.java:12)
select()
を使用してテストを実行すると、呼び出し (またはその他の失敗) の証拠が表示されないのはなぜsudo dtruss -a java SelectTest
ですか?
PID/THRD RELATIVE ELAPSD CPU SYSCALL(args) = return
45563/0x63a513: 85544 6 4 bind(0x412, 0x10DFC7738, 0x1C) = 0 0
45563/0x63a513: 85605 6 3 listen(0x412, 0x32, 0x32) = 0 0
45563/0x63a513: 85619 2 0 lseek(0x4, 0x37377AD, 0x0) = 57898925 0
45563/0x63a513: 85622 4 2 read(0x4, "PK\003\004\n\0", 0x1E) = 30 0
45563/0x63a513: 85622 1 0 lseek(0x4, 0x37377E0, 0x0) = 57898976 0
45563/0x63a513: 85627 5 4 read(0x4, "\312\376\272\276\0", 0x3447) = 13383 0
45563/0x63a513: 86150 37 33 write(0x2, "Exception in thread \"main\" ble\001\0", 0x1B) = 27 0