在linux中,Socket也是一个文件,所以如果一次存在太多套接字且超过最大打开文件,它将抛出异常:
java.net.SocketException: Too many open files
at sun.nio.ch.Net.socket0(Native Method)
at sun.nio.ch.Net.socket(Net.java:423)
at sun.nio.ch.Net.socket(Net.java:416)
at sun.nio.ch.SocketChannelImpl.<init>(SocketChannelImpl.java:104)
at sun.nio.ch.SelectorProviderImpl.openSocketChannel(SelectorProviderImpl.java:60)
at java.nio.channels.SocketChannel.open(SocketChannel.java:142)
直到现在我能理解,但我对下面的现象感到有些困惑。 我在终端执行了以下命令,找到最大打开文件号:
$ ulimit -n
1024
但实际上我通过以下代码创建了大约4091个套接字(SocketChannel):
while(true) {
new Thread(new Runnable() {
public void run() {
//...
try {
SocketChannel scChannel = SocketChannel.open();
scChannel.connect(new InetSocketAddress(hostname, port));
ByteBuffer buffer = ByteBuffer.allocate(1024);
scChannel.read(buffer);
} catch (IOException e) {
//...
}
}
}).start();
}
从控制台我知道,直到它创建4091 socketChannel,然后它抛出异常:
Start client 4091
java.net.SocketException: Too many open files
4091超过1024,为什么会这样? ulimit的结果不是最大打开文件的实际数量吗?
答案 0 :(得分:1)
根据上午的建议,我检查了jvm是否改变了ulimit。我发现jvm确实做了些什么。我用java代码执行了ulimit命令,如下所示:
ProcessBuilder pBuilder = new ProcessBuilder("sh","-c","ulimit -n");
Process p = pBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = reader.readLine();
while(line!=null){
System.out.println(line);
line = reader.readLine();
}
输出为4096 - 与终端输出不同。 但我不知道jvm如何以及何时何地改变了ulimit值。