产生原因
正常情况下,select()方法在没有事件时,程序一直阻塞在该方法,但是在没有任何事件的情况下,该方法被唤醒,但是在程序对seclectionKey进行遍历时,却没有任何key,导致程序一直在循环中不能执行下去,从而导致CPU100%。
具体解释为Linux kernel 2.6中的一部分,poll和epoll会对已经连接好后却突然中断连接的socket给eventSet返回一个集合,集合为POLLHUP,也可能为POLLERR,因为eventSet的事件集合发生了变化,导致Selector被唤醒。
Java官方解释
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6670302
问题复现
环境:Centos7 (其实只要是Linux系统就可以)
JDK版本:JDK6u3 (一定要是update3,后边版本对该问题修复,不太容易复现)
下载链接:https://www.oracle.com/java/technologies/javase-java-archive-javase6-downloads.html
客户端代码
import java.io.*;
import java.net.*;
public class TestClient {
private static final long SLEEP_PERIOD = 5000L; // 5 seconds
private String host;
private int port;
public TestClient(String host, int port) {
this.host = host;
this.port = port;
}
public static void main(String[] args) throws Throwable {
if (args.length < 2 || args[0].equals("127.0.0.1") || args[0].equals("localhost")) {
System.err.println("Usage : java TestClient <host name> <port> (host name should not be localhost)");
System.exit(0);
}
new TestClient(args[0], Integer.parseInt(args[1])).start();
}
public void start() throws Throwable {
Socket socket = new Socket(host, port);
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(
new OutputStreamWriter(socket.getOutputStream()),
true /* auto flush */);
out.println("abcdef");
System.out