ソケットをリッスンする Java プログラムを作成しました。
...
int port = getPort();
ServerSocket server = new ServerSocket(port);
server.accept()
...
Java 1.4、5、および 6 では、10 年ほどにわたって正常に動作します。しかし、Java 7 または 8 では、コンストラクターは常に次のバインド例外で失敗します。
java.net.BindException: Address already in use: JVM_Bind
at java.net.DualStackPlainSocketImpl.bind0(Native Method)
at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:106)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:382)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:190)
at java.net.ServerSocket.bind(ServerSocket.java:375)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
ポートは無料で、いくつかのテストの後、次の 2 つのことがわかりました。1. デバッグ オプションを
使用して JVM を起動すると、動作します
。
2. デバッグ オプションを設定しないと、コンストラクターの最初の呼び出しのみが失敗し、2 回目 (同じポートを使用) は常に成功します。したがって、次の醜いコードは回避策です。
-Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n
...
int port = getPort();
try {
server = new ServerSocket(port);
} catch(BindException e){
server = new ServerSocket(port);
}
server.setSoTimeout(0);
server.accept()
...
<br>
しかし、私は決してそれを使用したくありません:)
それを知った後、Tomcat 起動ファイルからデバッグ オプションを削除しました。驚くべきことに、デバッグ オプションなしで Java 7/8 を起動すると、Tomcat 7 には HTTP リスナーを作成するという同じ問題があります。ただし、Tomcat 7 には Java 7 以降が必要です。
Java 7/8 も Tomcat 7 も、ソケット通信などの重要な部分にバグがあった状態で出荷されたものではないと確信しています。
それで、私は何を間違っていますか?
Windows 7 Professional SP1 64 ビット、JDK 7 32/64 ビット、および JDK 8 64 ビットでテストしました。
アップデート;
同じ OS と jdk を使用する別のマシンでは、問題は発生しません。