7

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
4

1 に答える 1

0

ServerSocket.accept私はあなたが見たものを正確に呼ぶことを期待しています。

Java に対応する Berkeley ソケット呼び出しacceptは、listen()accept()です。

残念ながら、Linux で例外を再現できません。取得する前にすべての fd を使用した場合new ServerSocket(8080):

Exception in thread "main" java.lang.UnsatisfiedLinkError: /usr/lib/jvm/java-7-oracle/jre/lib/amd64/libnet.so: /usr/lib/jvm/java-7-oracle/jre/lib/amd64/libnet.so: cannot open shared object file: Too many open files
    at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    at java.lang.ClassLoader.loadLibrary1(ClassLoader.java:1939)
    at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1864)
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1846)
    at java.lang.Runtime.loadLibrary0(Runtime.java:845)
    at java.lang.System.loadLibrary(System.java:1084)
    at sun.security.action.LoadLibraryAction.run(LoadLibraryAction.java:67)
    at sun.security.action.LoadLibraryAction.run(LoadLibraryAction.java:47)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.AbstractPlainSocketImpl.<clinit>(AbstractPlainSocketImpl.java:80)
    at java.net.ServerSocket.setImpl(ServerSocket.java:289)
    at java.net.ServerSocket.<init>(ServerSocket.java:230)
    at java.net.ServerSocket.<init>(ServerSocket.java:128)
    at SelectTest.main(SelectTest.java:15)
于 2013-05-22T14:48:58.147 に答える