    public static IRubyObject select_static(IRuby runtime, IRubyObject[] args) {
        try {
        	boolean atLeastOneDescriptor = false;
            Selector selector = Selector.open();
            if (!args[0].isNil()) {
            	atLeastOneDescriptor = true;
                for (Iterator i = ((RubyArray) args[0]).getList().iterator(); i.hasNext(); ) {
                    IRubyObject obj = (IRubyObject) i.next();
                    registerSelect(selector, obj, SelectionKey.OP_READ|SelectionKey.OP_ACCEPT);
                }
            }
            if (args.length > 1 && !args[1].isNil()) {
            	atLeastOneDescriptor = true;
                for (Iterator i = ((RubyArray) args[0]).getList().iterator(); i.hasNext(); ) {
                    IRubyObject obj = (IRubyObject) i.next();
                    registerSelect(selector, obj, SelectionKey.OP_WRITE);
                }
            }
            if (args.length > 2 && !args[2].isNil()) {
            	atLeastOneDescriptor = true;
            }
            long timeout = 0;
            if(args.length > 3 && !args[3].isNil()) {
                if (args[3] instanceof RubyFloat) {
                    timeout = Math.round(((RubyFloat) args[3]).getDoubleValue() * 1000);
                } else {
                    timeout = Math.round(((RubyFixnum) args[3]).getDoubleValue() * 1000);
                }
                if (timeout < 0) {
                	throw runtime.newArgumentError("negative timeout given");
                }
            }
            if (!atLeastOneDescriptor) {
            	return runtime.getNil();
            }
            if(args.length > 3) {
                selector.select(timeout);
            } else {
                selector.select();
            }
            List r = new ArrayList();
            List w = new ArrayList();
            List e = new ArrayList();
            for (Iterator i = selector.selectedKeys().iterator(); i.hasNext(); ) {
                SelectionKey key = (SelectionKey) i.next();
                if ((key.interestOps() & key.readyOps()
                    & (SelectionKey.OP_READ|SelectionKey.OP_ACCEPT|SelectionKey.OP_CONNECT)) != 0) {
                    r.add(key.attachment());
                }
                if ((key.interestOps() & key.readyOps() & (SelectionKey.OP_WRITE)) != 0) {
                    w.add(key.attachment());
                }
            }
            for (Iterator i = selector.keys().iterator(); i.hasNext(); ) {
                SelectionKey key = (SelectionKey) i.next();
                SelectableChannel channel = key.channel();
                synchronized(channel.blockingLock()) {
                    boolean blocking = ((RubyIO) key.attachment()).getBlocking();
                    key.cancel();
                    channel.configureBlocking(blocking);
                }
            }
            selector.close();
            if (r.size() == 0 && w.size() == 0 && e.size() == 0) {
                return runtime.getNil();
            }
            List ret = new ArrayList();
            ret.add(RubyArray.newArray(runtime, r));
            ret.add(RubyArray.newArray(runtime, w));
            ret.add(RubyArray.newArray(runtime, e));
            return RubyArray.newArray(runtime, ret);
        } catch(IOException e) {
            throw runtime.newIOError(e.getMessage());
        }
    }

    public static IRubyObject select_static(IRuby runtime, IRubyObject[] args) {
        try {
        	boolean atLeastOneDescriptor = false;
            Selector selector = Selector.open();
            if (!args[0].isNil()) {
            	atLeastOneDescriptor = true;
                for (Iterator i = ((RubyArray) args[0]).getList().iterator(); i.hasNext(); ) {
                    IRubyObject obj = (IRubyObject) i.next();
                    registerSelect(selector, obj, SelectionKey.OP_READ|SelectionKey.OP_ACCEPT);
                }
            }
            if (args.length > 1 && !args[1].isNil()) {
            	atLeastOneDescriptor = true;
                for (Iterator i = ((RubyArray) args[1]).getList().iterator(); i.hasNext(); ) {
                    IRubyObject obj = (IRubyObject) i.next();
                    registerSelect(selector, obj, SelectionKey.OP_WRITE);
                }
            }
            if (args.length > 2 && !args[2].isNil()) {
            	atLeastOneDescriptor = true;
            }
            long timeout = 0;
            if(args.length > 3 && !args[3].isNil()) {
                if (args[3] instanceof RubyFloat) {
                    timeout = Math.round(((RubyFloat) args[3]).getDoubleValue() * 1000);
                } else {
                    timeout = Math.round(((RubyFixnum) args[3]).getDoubleValue() * 1000);
                }
                if (timeout < 0) {
                	throw runtime.newArgumentError("negative timeout given");
                }
            }
            if (!atLeastOneDescriptor) {
            	return runtime.getNil();
            }
            if(args.length > 3) {
                selector.select(timeout);
            } else {
                selector.select();
            }
            List r = new ArrayList();
            List w = new ArrayList();
            List e = new ArrayList();
            for (Iterator i = selector.selectedKeys().iterator(); i.hasNext(); ) {
                SelectionKey key = (SelectionKey) i.next();
                if ((key.interestOps() & key.readyOps()
                    & (SelectionKey.OP_READ|SelectionKey.OP_ACCEPT|SelectionKey.OP_CONNECT)) != 0) {
                    r.add(key.attachment());
                }
                if ((key.interestOps() & key.readyOps() & (SelectionKey.OP_WRITE)) != 0) {
                    w.add(key.attachment());
                }
            }
            for (Iterator i = selector.keys().iterator(); i.hasNext(); ) {
                SelectionKey key = (SelectionKey) i.next();
                SelectableChannel channel = key.channel();
                synchronized(channel.blockingLock()) {
                    boolean blocking = ((RubyIO) key.attachment()).getBlocking();
                    key.cancel();
                    channel.configureBlocking(blocking);
                }
            }
            selector.close();
            if (r.size() == 0 && w.size() == 0 && e.size() == 0) {
                return runtime.getNil();
            }
            List ret = new ArrayList();
            ret.add(RubyArray.newArray(runtime, r));
            ret.add(RubyArray.newArray(runtime, w));
            ret.add(RubyArray.newArray(runtime, e));
            return RubyArray.newArray(runtime, ret);
        } catch(IOException e) {
            throw runtime.newIOError(e.getMessage());
        }
    }
