diff --git a/README-en.md b/README-en.md index 995fbe61a..d9ebcc92f 100644 --- a/README-en.md +++ b/README-en.md @@ -2,7 +2,7 @@ # FireNio Project [![Website](https://img.shields.io/badge/website-firenio-green.svg)](https://www.firenio.com) -[![Maven central](https://img.shields.io/badge/maven-1.2.2-green.svg)](http://mvnrepository.com/artifact/com.firenio/firenio-all) +[![Maven central](https://img.shields.io/badge/maven-1.3.2-green.svg)](http://mvnrepository.com/artifact/com.firenio/firenio-all) [![License](https://img.shields.io/badge/License-Apache%202.0-585ac2.svg)](https://github.com/firenio/firenio/blob/master/LICENSE.txt) FireNio is an io framework which can build network project fast, it based on java nio, it is popular with Developers because of simple and easy of use APIs and high-performance. @@ -15,9 +15,10 @@ FireNio is an io framework which can build network project fast, it based on jav * WebSocket protocol, for detail: https://www.firenio.com/web-socket/chat/index.html * Protobase(custom) support text or binay, for detail {firenio-test} * easy to support reconnect (easy to support heart beat) - * supported ssl (jdkssl, openssl) - * load test - * [tfb benchmark](https://www.techempower.com/benchmarks/#section=test&runid=76a34044-54d6-4349-adfe-863c2d5ae756&hw=ph&test=plaintext) + * supported ssl (JdkSSL & OpenSSL) + * TFB load test + * [TFB Benchmark(Physical)](https://www.techempower.com/benchmarks/#section=data-r18&hw=ph&test=plaintext) + * [TFB Benchmark(Cloud)](https://www.techempower.com/benchmarks/#section=data-r18&hw=cl&test=plaintext) ## Quick Start @@ -27,7 +28,7 @@ FireNio is an io framework which can build network project fast, it based on jav com.firenio firenio-all - 1.2.2 + 1.3.2 ``` diff --git a/README.md b/README.md index 2f2d4d6f2..419191a0e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # FireNio Project [![Website](https://img.shields.io/badge/website-firenio-green.svg)](https://www.firenio.com) -[![Maven central](https://img.shields.io/badge/maven-1.2.2-green.svg)](http://mvnrepository.com/artifact/com.firenio/firenio-all) +[![Maven central](https://img.shields.io/badge/maven-1.3.2-green.svg)](http://mvnrepository.com/artifact/com.firenio/firenio-all) [![License](https://img.shields.io/badge/License-Apache%202.0-585ac2.svg)](https://github.com/firenio/firenio/blob/master/LICENSE.txt) FireNio是基于java nio开发的一款可快速构建网络通讯项目的异步IO框架,其以简单易用的API和优良的性能深受开发者喜爱。 @@ -15,9 +15,11 @@ FireNio是基于java nio开发的一款可快速构建网络通讯项目的异 * WebSocket协议,示例: https://www.firenio.com/web-socket/chat/index.html * Protobase(自定义协议),支持传输文本或二进制数据 * 轻松实现断线重连(轻松实现心跳机制) - * 支持SSL(jdkssl,openssl) - * 压力测试 - * [tfb benchmark](https://www.techempower.com/benchmarks/#section=test&runid=76a34044-54d6-4349-adfe-863c2d5ae756&hw=ph&test=plaintext) + * 支持SSL(JdkSSL & OpenSSL) + * TFB压力测试 + * [TFB Benchmark(Physical)](https://www.techempower.com/benchmarks/#section=data-r18&hw=ph&test=plaintext) + * [TFB Benchmark(Cloud)](https://www.techempower.com/benchmarks/#section=data-r18&hw=cl&test=plaintext) + ## 快速入门 @@ -27,7 +29,7 @@ FireNio是基于java nio开发的一款可快速构建网络通讯项目的异 com.firenio firenio-all - 1.2.2 + 1.3.2 ``` diff --git a/firenio-all/pom.xml b/firenio-all/pom.xml index 1978872ef..c8530b9c8 100644 --- a/firenio-all/pom.xml +++ b/firenio-all/pom.xml @@ -10,7 +10,7 @@ com.firenio firenio - 1.2.2 + 1.3.2 ../firenio/pom.xml @@ -93,7 +93,7 @@ org.wildfly.openssl wildfly-openssl-java - 1.0.6.Final + 1.0.8.Final provided diff --git a/firenio-codec/pom.xml b/firenio-codec/pom.xml index e8a66af8f..6d3c13c39 100644 --- a/firenio-codec/pom.xml +++ b/firenio-codec/pom.xml @@ -10,7 +10,7 @@ com.firenio firenio - 1.2.2 + 1.3.2 ../firenio/pom.xml diff --git a/firenio-codec/src/main/java/com/firenio/codec/http11/ClientHttpCodec.java b/firenio-codec/src/main/java/com/firenio/codec/http11/ClientHttpCodec.java index 393e6aa52..828d50da5 100644 --- a/firenio-codec/src/main/java/com/firenio/codec/http11/ClientHttpCodec.java +++ b/firenio-codec/src/main/java/com/firenio/codec/http11/ClientHttpCodec.java @@ -63,8 +63,8 @@ public ByteBuf encode(Channel ch, Frame frame) { boolean isArray = false; int write_size = 0; if (content instanceof ByteBuf) { - contentBuf = ((ByteBuf) content).flip(); - write_size = contentBuf.limit(); + contentBuf = ((ByteBuf) content); + write_size = contentBuf.writeIndex(); } else if (content instanceof byte[]) { isArray = true; contentArray = (byte[]) content; @@ -77,12 +77,12 @@ public ByteBuf encode(Channel ch, Frame frame) { int len_len = 32 - len_idx; int len = mtd_bytes.length + 1 + url_bytes.length + PROTOCOL.length + len_len + 2; int header_size = 0; - List bytes_array = getEncodeBytesArray(FastThreadLocal.get()); + List bytes_array = (List) FastThreadLocal.get().getList(); IntMap headers = f.getRequestHeaders(); if (headers != null) { headers.remove(HttpHeader.Content_Length.getId()); for (headers.scan(); headers.hasNext(); ) { - byte[] k = HttpHeader.get(headers.nextKey()).getBytes(); + byte[] k = HttpHeader.get(headers.key()).getBytes(); byte[] v = headers.value().getBytes(); if (v == null) { continue; @@ -100,34 +100,34 @@ public ByteBuf encode(Channel ch, Frame frame) { len += write_size; } ByteBuf buf = ch.alloc().allocate(len); - buf.putBytes(mtd_bytes); - buf.putByte(SPACE); - buf.putBytes(url_bytes); - buf.putBytes(PROTOCOL); - buf.putBytes(byte32, len_idx, len_len); - buf.putByte(R); - buf.putByte(N); + buf.writeBytes(mtd_bytes); + buf.writeByte(SPACE); + buf.writeBytes(url_bytes); + buf.writeBytes(PROTOCOL); + buf.writeBytes(byte32, len_idx, len_len); + buf.writeByte(R); + buf.writeByte(N); int j = 0; for (int i = 0; i < header_size; i++) { - buf.putBytes(bytes_array.get(j++)); - buf.putByte((byte) ':'); - buf.putByte(SPACE); - buf.putBytes(bytes_array.get(j++)); - buf.putByte(R); - buf.putByte(N); + buf.writeBytes(bytes_array.get(j++)); + buf.writeByte((byte) ':'); + buf.writeByte(SPACE); + buf.writeBytes(bytes_array.get(j++)); + buf.writeByte(R); + buf.writeByte(N); } - buf.putByte(R); - buf.putByte(N); + buf.writeByte(R); + buf.writeByte(N); if (write_size > 0) { if (isArray) { - buf.putBytes(contentArray); + buf.writeBytes(contentArray); } else { - ch.write(buf.flip()); + ch.write(buf); ch.write(contentBuf); return null; } } - return buf.flip(); + return buf; } private String getRequestURI(HttpFrame frame) { diff --git a/firenio-codec/src/main/java/com/firenio/codec/http11/HttpCodec.java b/firenio-codec/src/main/java/com/firenio/codec/http11/HttpCodec.java index c76834374..f02410a15 100644 --- a/firenio-codec/src/main/java/com/firenio/codec/http11/HttpCodec.java +++ b/firenio-codec/src/main/java/com/firenio/codec/http11/HttpCodec.java @@ -22,8 +22,10 @@ import com.firenio.Develop; import com.firenio.buffer.ByteBuf; +import com.firenio.collection.AttributeKey; import com.firenio.collection.ByteTree; import com.firenio.collection.IntMap; +import com.firenio.collection.Stack; import com.firenio.common.ByteUtil; import com.firenio.common.Util; import com.firenio.component.Channel; @@ -37,24 +39,23 @@ */ public class HttpCodec extends ProtocolCodec { - static final byte[] CONTENT_LENGTH_MATCH = ByteUtil.b("Content-Length:"); - static final int decode_state_body = 2; - static final int decode_state_complete = 3; - static final int decode_state_header = 1; - static final int decode_state_line_one = 0; - static final int encode_bytes_arrays_index = nextIndexedVariablesIndex(); - static final int content_len_index = nextIndexedVariablesIndex(); - static final String FRAME_CACHE_KEY = "_HTTP_FRAME_CACHE_KEY"; - static final byte N = '\n'; - static final IOException OVER_LIMIT = EXCEPTION("over limit"); - static final IOException ILLEGAL_METHOD = EXCEPTION("illegal http method"); - static final byte R = '\r'; - static final byte SPACE = ' '; - static final int NUM_GET = ByteUtil.getInt("GET ".getBytes(), 0); - static final int NUM_POST = ByteUtil.getInt("POST".getBytes(), 0); + static final byte[] CONTENT_LENGTH_MATCH = ByteUtil.b("Content-Length:"); + static final int decode_state_body = 2; + static final int decode_state_complete = 3; + static final int decode_state_header = 1; + static final int decode_state_line_one = 0; + static final AttributeKey> FRAME_CACHE_KEY = NioEventLoop.valueOfKey("http_frame_cache_key"); + static final byte N = '\n'; + static final IOException OVER_LIMIT = EXCEPTION("over writeIndex"); + static final IOException ILLEGAL_METHOD = EXCEPTION("illegal http method"); + static final byte R = '\r'; + static final byte SPACE = ' '; + static final int NUM_GET = ByteUtil.getIntLE("GET ".getBytes(), 0); + static final int NUM_POST = ByteUtil.getIntLE("POST".getBytes(), 0); private final int blimit; private final byte[][] cl_bytes = new byte[1024][]; + private final int com_threshold; private final int hlimit; private final int fcache; private final boolean lite; @@ -79,20 +80,21 @@ public HttpCodec(String server, int frameCache) { } public HttpCodec(String server, int frameCache, boolean lite, boolean inline) { - this(server, frameCache, 1024 * 8, 1024 * 256, lite, inline, null); + this(server, frameCache, 1024 * 8, 1024 * 256, 1024 * 4, lite, inline, null); } public HttpCodec(String server, int frameCache, boolean lite, boolean inline, ByteTree cachedUrls) { - this(server, frameCache, 1024 * 8, 1024 * 256, lite, inline, cachedUrls); + this(server, frameCache, 1024 * 8, 1024 * 256, 1024 * 4, lite, inline, cachedUrls); } - public HttpCodec(String server, int fcache, int hlimit, int blimit, boolean lite, boolean inline, ByteTree cachedUrls) { + public HttpCodec(String server, int fcache, int hlimit, int blimit, int com_threshold, boolean lite, boolean inline, ByteTree cachedUrls) { this.lite = lite; this.inline = inline; this.hlimit = hlimit; this.blimit = blimit; this.fcache = fcache; this.cached_urls = cachedUrls; + this.com_threshold = com_threshold; ByteBuffer temp = ByteBuffer.allocate(128); if (server == null) { temp.put(ByteUtil.b("\r\nContent-Length: ")); @@ -114,7 +116,7 @@ public HttpCodec(String server, int fcache, int hlimit, int blimit, boolean lite private static String parse_url(ByteBuf src, int url_start, int url_end) { StringBuilder line = FastThreadLocal.get().getStringBuilder(); for (int i = url_start; i < url_end; i++) { - line.append((char) (src.absByte(i) & 0xff)); + line.append((char) (src.getByteAbs(i) & 0xff)); } return line.toString(); } @@ -161,14 +163,9 @@ protected static void parse_url(HttpFrame f, int skip, CharSequence line) { } } - @SuppressWarnings("unchecked") - static List getEncodeBytesArray(FastThreadLocal l) { - return (List) l.getList(encode_bytes_arrays_index); - } - private static int read_line(StringBuilder line, ByteBuf src, int abs_pos, int length, int limit) throws IOException { int maybeRead = limit - length; - int s_limit = src.absLimit(); + int s_limit = src.absWriteIndex(); int remaining = s_limit - abs_pos; if (remaining > maybeRead) { int i = read_line(line, src, abs_pos, abs_pos + maybeRead); @@ -183,7 +180,7 @@ private static int read_line(StringBuilder line, ByteBuf src, int abs_pos, int l private static int read_line(StringBuilder line, ByteBuf src, int abs_pos, int abs_limit) { for (int i = abs_pos; i < abs_limit; i++) { - byte b = src.absByte(i); + byte b = src.getByteAbs(i); if (b == N) { line.setLength(line.length() - 1); return i + 1; @@ -196,7 +193,7 @@ private static int read_line(StringBuilder line, ByteBuf src, int abs_pos, int a private static int read_line_range(ByteBuf src, int abs_pos, int length, int limit) throws IOException { int maybeRead = limit - length; - int s_limit = src.absLimit(); + int s_limit = src.absWriteIndex(); int remaining = s_limit - abs_pos; if (remaining > maybeRead) { int res_p = src.indexOf(N, abs_pos, maybeRead); @@ -214,7 +211,7 @@ private static boolean start_with(ByteBuf src, int ps, int pe, byte[] match) { return false; } for (int i = 0; i < match.length; i++) { - if (src.absByte(ps + i) != match[i]) { + if (src.getByteAbs(ps + i) != match[i]) { return false; } } @@ -239,7 +236,7 @@ private HttpFrame alloc_frame(NioEventLoop el) { private int decode_lite(ByteBuf src, HttpFrame f) throws IOException { int decode_state = f.getDecodeState(); - int abs_pos = src.absPos(); + int abs_pos = src.absReadIndex(); int h_len = f.getHeaderLength(); if (decode_state == decode_state_line_one) { int l_end = src.indexOf(N); @@ -249,7 +246,7 @@ private int decode_lite(ByteBuf src, HttpFrame f) throws IOException { h_len += (l_end - abs_pos); decode_state = decode_state_header; int url_start = abs_pos; - int num = src.getInt(abs_pos); + int num = src.getIntLE(abs_pos); if (num == NUM_GET) { f.setMethod(HttpMethod.GET); url_start += 4; @@ -276,7 +273,7 @@ private int decode_lite(ByteBuf src, HttpFrame f) throws IOException { } else { StringBuilder line = FastThreadLocal.get().getStringBuilder(); for (int i = url_start; i < url_end; i++) { - line.append((char) (src.absByte(i) & 0xff)); + line.append((char) (src.getByteAbs(i) & 0xff)); } int re_qmark = qmark - url_start; parse_kv(f.getRequestParams(), line, re_qmark + 1, line.length(), '=', '&'); @@ -291,7 +288,7 @@ private int decode_lite(ByteBuf src, HttpFrame f) throws IOException { int pe = read_line_range(src, ps, h_len, hlimit); if (pe == -1) { f.setHeaderLength(h_len); - src.absPos(abs_pos); + src.absReadIndex(abs_pos); break; } abs_pos = pe-- + 1; @@ -306,7 +303,7 @@ private int decode_lite(ByteBuf src, HttpFrame f) throws IOException { } decode_state = decode_state_body; } - src.absPos(abs_pos); + src.absReadIndex(abs_pos); break; } else { if (!f.isGet()) { @@ -318,7 +315,7 @@ private int decode_lite(ByteBuf src, HttpFrame f) throws IOException { } int ct_len = 0; for (int i = cps; i < pe; i++) { - ct_len = (src.absByte(i) - '0') + ct_len * 10; + ct_len = (src.getByteAbs(i) - '0') + ct_len * 10; } f.setContentLength(ct_len); } @@ -333,7 +330,7 @@ private int decode_full(ByteBuf src, HttpFrame f) throws IOException { StringBuilder line = FastThreadLocal.get().getStringBuilder(); int decode_state = f.getDecodeState(); int h_len = f.getHeaderLength(); - int abs_pos = src.absPos(); + int abs_pos = src.absReadIndex(); if (decode_state == decode_state_line_one) { int l_end = read_line(line, src, abs_pos, 0, hlimit); if (l_end == -1) { @@ -350,14 +347,14 @@ private int decode_full(ByteBuf src, HttpFrame f) throws IOException { line.setLength(0); int pn = read_line(line, src, abs_pos, h_len, hlimit); if (pn == -1) { - src.absPos(abs_pos); + src.absReadIndex(abs_pos); f.setHeaderLength(h_len); break; } abs_pos = pn; h_len += line.length(); if (line.length() == 0) { - src.absPos(abs_pos); + src.absReadIndex(abs_pos); decode_state = header_complete(f); break; } else { @@ -408,12 +405,12 @@ public Frame decode(Channel ch, ByteBuf src) throws Exception { int decode_remain_body(Channel ch, ByteBuf src, HttpFrame f) { int contentLength = f.getContentLength(); - int remain = src.remaining(); + int remain = src.readableBytes(); if (remain < contentLength) { return decode_state_body; } else { byte[] content = new byte[contentLength]; - src.getBytes(content); + src.readBytes(content); if (f.isForm()) { String param = new String(content, ch.getCharset()); parse_kv(f.getRequestParams(), param, 0, param.length(), '=', '&'); @@ -424,25 +421,13 @@ int decode_remain_body(Channel ch, ByteBuf src, HttpFrame f) { } } - private byte[] get_c_len_buf(FastThreadLocal l) { - byte[] bb = (byte[]) l.getIndexedVariable(content_len_index); - if (bb == null) { - int limit = cl_buf.limit(); - bb = new byte[cl_buf.limit() + 16]; - cl_buf.get(bb, 0, limit); - cl_buf.clear().limit(limit); - l.setIndexedVariable(content_len_index, bb); - } - return bb; - } - @Override public ByteBuf encode(final Channel ch, Frame frame) { boolean inline = this.inline; HttpFrame f = (HttpFrame) frame; FastThreadLocal l = FastThreadLocal.get(); HttpAttachment att = (HttpAttachment) ch.getAttachment(); - List bytes_array = getEncodeBytesArray(l); + List bytes_array = (List) l.getList(); Object content = f.getContent(); ByteBuf content_buf = null; byte[] content_array = null; @@ -453,8 +438,8 @@ public ByteBuf encode(final Channel ch, Frame frame) { boolean is_array = false; int write_size = 0; if (content instanceof ByteBuf) { - content_buf = ((ByteBuf) content).flip(); - write_size = content_buf.limit(); + content_buf = ((ByteBuf) content); + write_size = content_buf.readableBytes(); } else if (content instanceof byte[]) { is_array = true; content_array = (byte[]) content; @@ -466,7 +451,7 @@ public ByteBuf encode(final Channel ch, Frame frame) { cl_len_bytes = cl_bytes[write_size]; cl_len = cl_len_bytes.length; } else { - cl_len_bytes = get_c_len_buf(l); + cl_len_bytes = cl_buf.array(); int tmp_len = cl_buf.limit(); int len_idx = Util.valueOf(write_size, cl_len_bytes); int num_len = cl_len_bytes.length - len_idx; @@ -482,7 +467,7 @@ public ByteBuf encode(final Channel ch, Frame frame) { IntMap headers = f.getResponseHeaders(); if (headers != null) { for (headers.scan(); headers.hasNext(); ) { - byte[] k = HttpHeader.get(headers.nextKey()).getBytes(); + byte[] k = HttpHeader.get(headers.key()).getBytes(); byte[] v = headers.value(); h_size++; bytes_array.add(k); @@ -500,13 +485,11 @@ public ByteBuf encode(final Channel ch, Frame frame) { boolean offer = true; if (inline) { buf = att.getLastWriteBuf(); - if (buf.isReleased() || buf.capacity() - buf.limit() < len) { + if (buf.isReleased()) { buf = ch.alloc().allocate(len); att.setLastWriteBuf(buf); } else { offer = false; - buf.absPos(buf.absLimit()); - buf.limit(buf.capacity()); } } else { if (Develop.BUF_DEBUG) { @@ -515,49 +498,56 @@ public ByteBuf encode(final Channel ch, Frame frame) { buf = ch.alloc().allocate(len); } } - buf.putBytes(head_bytes); - buf.putBytes(cl_len_bytes, 0, cl_len); + buf.writeBytes(head_bytes); + buf.writeBytes(cl_len_bytes, 0, cl_len); if (conn_bytes != null) { - buf.putBytes(conn_bytes); + buf.writeBytes(conn_bytes); } if (type_bytes != null) { - buf.putBytes(type_bytes); + buf.writeBytes(type_bytes); } if (date_bytes != null) { - buf.putBytes(date_bytes); + buf.writeBytes(date_bytes); } - buf.putByte(R); - buf.putByte(N); + buf.writeByte(R); + buf.writeByte(N); if (h_size > 0) { put_headers(buf, bytes_array, h_size); } - buf.putByte(R); - buf.putByte(N); + buf.writeByte(R); + buf.writeByte(N); if (write_size > 0) { - if (is_array) { - buf.putBytes(content_array); - } else { + if (write_size > com_threshold) { + if (is_array) { + content_buf = ByteBuf.wrap(content_array); + } if (inline) { att.setLastWriteBuf(ByteBuf.empty()); } - ch.write(buf.flip()); - ch.write(content_buf); + ch.write(buf); + ch.writeAndFlush(content_buf); return null; + } else { + if (is_array) { + buf.writeBytes(content_array); + } else { + buf.writeBytes(content_buf); + content_buf.release(); + } } } - buf.flip(); return offer ? buf : null; } private void put_headers(ByteBuf buf, List encode_bytes_array, int header_size) { int j = 0; for (int i = 0; i < header_size; i++) { - buf.putBytes(encode_bytes_array.get(j++)); - buf.putByte((byte) ':'); - buf.putByte(SPACE); - buf.putBytes(encode_bytes_array.get(j++)); - buf.putByte(R); - buf.putByte(N); + buf.writeBytes(encode_bytes_array.get(j++)); + buf.writeByte((byte) ':'); + buf.writeByte(SPACE); + buf.writeBytes(encode_bytes_array.get(j++)); + buf.writeByte(R); + buf.writeByte(N); } } @@ -603,10 +593,11 @@ int header_complete(HttpFrame f) throws IOException { } protected void parse_line_one(HttpFrame f, CharSequence line) throws IOException { - if (line.charAt(0) == 'G' && line.charAt(1) == 'E' && line.charAt(2) == 'T') { + int v = (line.charAt(0) << 0) | (line.charAt(1) << 8) | (line.charAt(2) << 16) | (line.charAt(3) << 24); + if (v == NUM_GET) { f.setMethod(HttpMethod.GET); parse_url(f, 4, line); - } else if (line.charAt(0) == 'P' && line.charAt(1) == 'O' && line.charAt(2) == 'S' && line.charAt(3) == 'T') { + } else if (v == NUM_POST) { f.setMethod(HttpMethod.POST); parse_url(f, 5, line); } else { diff --git a/firenio-codec/src/main/java/com/firenio/codec/http11/HttpHeader.java b/firenio-codec/src/main/java/com/firenio/codec/http11/HttpHeader.java index 13dceaedb..3c06716cf 100644 --- a/firenio-codec/src/main/java/com/firenio/codec/http11/HttpHeader.java +++ b/firenio-codec/src/main/java/com/firenio/codec/http11/HttpHeader.java @@ -70,15 +70,11 @@ public enum HttpHeader { private static final HttpHeader[] enums; static { - try { - enums = new HttpHeader[values().length]; - for (HttpHeader value : values()) { - enums[value.id] = value; - ALL.put(value.getKey(), value); - ALL.put(value.getLowercase(), value); - } - } catch (Exception e) { - throw new RuntimeException(e); + enums = new HttpHeader[values().length]; + for (HttpHeader value : values()) { + enums[value.id] = value; + ALL.put(value.getKey(), value); + ALL.put(value.getLowercase(), value); } } diff --git a/firenio-codec/src/main/java/com/firenio/codec/http11/HttpStatic.java b/firenio-codec/src/main/java/com/firenio/codec/http11/HttpStatic.java index 76402bf1f..33442e467 100644 --- a/firenio-codec/src/main/java/com/firenio/codec/http11/HttpStatic.java +++ b/firenio-codec/src/main/java/com/firenio/codec/http11/HttpStatic.java @@ -21,57 +21,57 @@ public final class HttpStatic { // public static final String application_js_utf8 = "application/x-javascript;charset=utf-8"; - // public static final byte[] application_js_utf8_bytes = application_js_utf8.getBytes(); + // public static final byte[] application_js_utf8_bytes = application_js_utf8.readBytes(); // // public static final String application_json = "application/json"; - // public static final byte[] application_json_bytes = application_json.getBytes(); + // public static final byte[] application_json_bytes = application_json.readBytes(); // // public static final String application_stream = "application/octet-stream"; - // public static final byte[] application_stream_bytes = application_stream.getBytes(); + // public static final byte[] application_stream_bytes = application_stream.readBytes(); // // public static final String application_urlencoded = "application/x-www-form-urlencoded"; - // public static final byte[] application_urlencoded_bytes = application_urlencoded.getBytes(); + // public static final byte[] application_urlencoded_bytes = application_urlencoded.readBytes(); // // public static final String image_gif = "image/gif"; - // public static final byte[] image_gif_bytes = image_gif.getBytes(); + // public static final byte[] image_gif_bytes = image_gif.readBytes(); // // public static final String image_icon = "image/x-icon"; - // public static final byte[] image_icon_bytes = image_icon.getBytes(); + // public static final byte[] image_icon_bytes = image_icon.readBytes(); // // public static final String image_jpeg = "image/jpeg"; - // public static final byte[] image_jpeg_bytes = image_jpeg.getBytes(); + // public static final byte[] image_jpeg_bytes = image_jpeg.readBytes(); // // public static final String image_png = "image/png"; - // public static final byte[] image_png_bytes = image_png.getBytes(); + // public static final byte[] image_png_bytes = image_png.readBytes(); // // public static final String multipart = "multipart/form-data"; - // public static final byte[] multipart_bytes = multipart.getBytes(); + // public static final byte[] multipart_bytes = multipart.readBytes(); // public static final String server_firenio = "firenio"; public static final byte[] server_firenio_bytes = server_firenio.getBytes(); // // public static final String text_css_utf8 = "text/css;charset=utf-8"; - // public static final byte[] text_css_utf8_bytes = text_css_utf8.getBytes(); + // public static final byte[] text_css_utf8_bytes = text_css_utf8.readBytes(); // // public static final String text_html_utf8 = "text/html;charset=utf-8"; - // public static final byte[] text_html_utf8_bytes = text_html_utf8.getBytes(); + // public static final byte[] text_html_utf8_bytes = text_html_utf8.readBytes(); // // public static final String text_plain = "text/plain"; - // public static final byte[] text_plain_bytes = text_plain.getBytes(); + // public static final byte[] text_plain_bytes = text_plain.readBytes(); // // public static final String text_plain_gbk = "text/plain;charset=gbk"; - // public static final byte[] text_plain_gbk_bytes = text_plain_gbk.getBytes(); + // public static final byte[] text_plain_gbk_bytes = text_plain_gbk.readBytes(); // // public static final String text_plain_utf8 = "text/plain;charset=utf-8"; - // public static final byte[] text_plain_utf8_bytes = text_plain_utf8.getBytes(); + // public static final byte[] text_plain_utf8_bytes = text_plain_utf8.readBytes(); // // public static final String upgrade = "Upgrade"; - // public static final byte[] upgrade_bytes = upgrade.getBytes(); + // public static final byte[] upgrade_bytes = upgrade.readBytes(); // public static final String websocket = "WebSocket"; public static final byte[] websocket_bytes = websocket.getBytes(); // public static final String = ""; - // public static final byte[] _bytes = "".getBytes(); + // public static final byte[] _bytes = "".readBytes(); } diff --git a/firenio-codec/src/main/java/com/firenio/codec/http11/KMPUtil.java b/firenio-codec/src/main/java/com/firenio/codec/http11/KMPUtil.java index c199f957a..761b28547 100644 --- a/firenio-codec/src/main/java/com/firenio/codec/http11/KMPUtil.java +++ b/firenio-codec/src/main/java/com/firenio/codec/http11/KMPUtil.java @@ -15,7 +15,6 @@ */ package com.firenio.codec.http11; -import com.firenio.collection.IntArray; import com.firenio.common.Util; //关键字:前缀,后缀,部分匹配表 @@ -28,53 +27,50 @@ public class KMPUtil { private String match_value; public KMPUtil(String value) { - this.initialize(value); - } - - public static void main(String[] args) { - - String s1 = "1111111111111111111211111111112111121111211111111"; - - String match = "1112"; - - KMPUtil kmp = new KMPUtil(match); - - System.out.println(kmp.match_all(s1)); - - } - - private void initialize(String value) { if (Util.isNullOrBlank(value)) { throw new IllegalArgumentException("null value"); } this.match_value = value; this.match_array = match_value.toCharArray(); - this.match_table = new int[match_value.length()]; - this.initialize_part_match_table(); + this.match_table = new int[match_value.length() - 1]; + int length = this.match_value.length() - 1; + // 只需要计算长度减一位的部分匹配表,因为最后一位如果也匹配整个字符串就匹配了 + // 直接从第二位开始比较 + for (int i = 1; i < length; i++) { + match_table[i] = init_table(value, i + 1); + } } - private void initialize_part_match_table() { - int length = this.match_value.length(); - // 直接从两位开始比较 - for (int i = 2; i < length; i++) { - match_table[i] = initialize_part_match_table0(match_array, i); + public static void main(String[] args) { + + String src = "ABC ABCA ABCABA"; + String match = "ABCAB"; + src = "AABAABAABC"; + match = "AABAABC"; + KMPUtil kmp = new KMPUtil(match); + int find = 0; + for (; ; ) { + find = kmp.match(src, find); + if (find == -1) { + break; + } + System.out.println(find); + find += match.length(); } + } - private int initialize_part_match_table0(char[] array, int length) { + private int init_table(String value, int length) { int e = 0; WORD: for (int i = 1; i < length; i++) { - int t = 0; - int p = 0; - int s = length - i; for (int j = 0; j < i; j++) { - if (array[p++] != array[s++]) { + int fix = length - i; + if (value.charAt(j) != value.charAt(fix + j)) { continue WORD; } - t++; } - e = t; + e = i; } return e; } @@ -83,70 +79,35 @@ public int match(String value) { return match(value, 0); } - public int match(String value, int begin) { - if (Util.isNullOrBlank(value) || begin < 0) { - return -1; - } - if (value.length() - begin < this.match_array.length) { + public int match(String value, int offset) { + if (value.length() - offset < match_array.length) { return -1; } - int source_length = value.length(); - int index = begin; - int match_length = this.match_array.length; - char[] match_array = this.match_array; - int[] match_table = this.match_table; - LOOP: - for (; index < source_length; ) { - for (int i = 0; i < match_length; i++) { - if (value.charAt(index + i) != match_array[i]) { - if (i == 0) { - index++; - } else { - index += (i - match_table[i]); - } - continue LOOP; + int src_length = value.length(); + int mat_index = 0; + int src_index = offset; + int match_length = this.match_array.length; + char[] match_array = this.match_array; + int[] match_table = this.match_table; + for (; src_index < src_length; ) { + char s_c = value.charAt(src_index); + char m_c = match_array[mat_index]; + if (s_c == m_c) { + mat_index++; + src_index++; + if (mat_index == match_length) { + return src_index - match_length; + } + } else { + if (mat_index == 0) { + src_index++; + } else { + // 第mat_index位不匹配,查找这以前的匹配情况(-1) + mat_index = match_table[mat_index - 1]; } } - return index; } return -1; } - public IntArray match_all(String value) { - if (Util.isNullOrBlank(value)) { - return null; - } - if (value.length() < match_value.length()) { - return null; - } - IntArray matchs = new IntArray(); - if (value.equals(match_value)) { - matchs.add(0); - return matchs; - } - int source_length = value.length(); - int index = 0; - int match_length = this.match_array.length; - char[] match_array = this.match_array; - int[] match_table = this.match_table; - LOOP: - for (; index < source_length; ) { - if (source_length - index < match_length) { - break; - } - for (int i = 0; i < match_length; i++) { - if (value.charAt(index + i) != match_array[i]) { - if (i == 0) { - index++; - } else { - index += (i - match_table[i]); - } - continue LOOP; - } - } - matchs.add(index); - index += match_length; - } - return matchs; - } } diff --git a/firenio-codec/src/main/java/com/firenio/codec/http11/WebSocketCodec.java b/firenio-codec/src/main/java/com/firenio/codec/http11/WebSocketCodec.java index fe8268826..3245ae605 100644 --- a/firenio-codec/src/main/java/com/firenio/codec/http11/WebSocketCodec.java +++ b/firenio-codec/src/main/java/com/firenio/codec/http11/WebSocketCodec.java @@ -16,12 +16,10 @@ package com.firenio.codec.http11; import java.io.IOException; -import java.util.List; import com.firenio.buffer.ByteBuf; import com.firenio.component.Channel; import com.firenio.component.Frame; -import com.firenio.component.NioEventLoop; import com.firenio.component.ProtocolCodec; //FIXME 心跳貌似由服务端发起 @@ -53,11 +51,10 @@ */ public final class WebSocketCodec extends ProtocolCodec { - public static final String FRAME_STACK_KEY = "FRAME_STACK_KEY_WS"; public static final int HEADER_LENGTH = 2; public static final int MAX_HEADER_LENGTH = 10; public static final int MAX_UNSIGNED_SHORT = 0xffff; - public static final IOException OVER_LIMIT = EXCEPTION("over limit"); + public static final IOException OVER_LIMIT = EXCEPTION("over writeIndex"); public static final IOException ILLEGAL_PROTOCOL = EXCEPTION("illegal protocol"); public static final String PROTOCOL_ID = "WebSocket"; public static final byte TYPE_BINARY = 2; @@ -75,39 +72,32 @@ public final class WebSocketCodec extends ProtocolCodec { byte o_h0 = (byte) (1 << 7); byte o_h1 = (byte) (0 << 7); - PING = ByteBuf.direct(2); - PONG = ByteBuf.direct(2); - PING.putByte((byte) (o_h0 | TYPE_PING)); - PING.putByte((byte) (o_h1 | 0)); - PONG.putByte((byte) (o_h0 | TYPE_PONG)); - PONG.putByte((byte) (o_h1 | 0)); - PING.flip(); - PONG.flip(); + PING = ByteBuf.buffer(2); + PONG = ByteBuf.buffer(2); + PING.writeByte((byte) (o_h0 | TYPE_PING)); + PING.writeByte((byte) (o_h1 | 0)); + PONG.writeByte((byte) (o_h0 | TYPE_PONG)); + PONG.writeByte((byte) (o_h1 | 0)); } - private final int frameStackSize; private final int limit; public WebSocketCodec() { this(1024 * 64); } - public WebSocketCodec(int limit) { - this(limit, 0); - } - public WebSocketCodec(int limit, int frameStackSize) { + public WebSocketCodec(int limit) { this.limit = limit; - this.frameStackSize = frameStackSize; } @Override public Frame decode(Channel ch, ByteBuf src) throws IOException { - if (src.remaining() < HEADER_LENGTH) { + if (src.readableBytes() < HEADER_LENGTH) { return null; } - byte b0 = src.getByte(); - byte b1 = src.getByte(); + byte b0 = src.readByte(); + byte b1 = src.readByte(); int skip = 2; int mask_len = 0; boolean has_mask = (b1 & 0b10000000) != 0; @@ -118,19 +108,19 @@ public Frame decode(Channel ch, ByteBuf src) throws IOException { if (payload_len < 126) { } else if (payload_len == 126) { - if (src.remaining() < 2) { - src.skip(-skip); + if (src.readableBytes() < 2) { + src.skipRead(-skip); return null; } skip += 2; - payload_len = src.getUnsignedShort(); + payload_len = src.readUnsignedShort(); } else { - if (src.remaining() < 8) { - src.skip(-skip); + if (src.readableBytes() < 8) { + src.skipRead(-skip); return null; } skip += 8; - payload_len = (int) src.getLong(); + payload_len = (int) src.readLong(); if (payload_len < 0) { throw OVER_LIMIT; } @@ -138,8 +128,8 @@ public Frame decode(Channel ch, ByteBuf src) throws IOException { if (payload_len > limit) { throw OVER_LIMIT; } - if (src.remaining() < payload_len + mask_len) { - src.skip(-skip); + if (src.readableBytes() < payload_len + mask_len) { + src.skipRead(-skip); return null; } byte opcode = (byte) (b0 & 0xF); @@ -154,11 +144,11 @@ public Frame decode(Channel ch, ByteBuf src) throws IOException { } byte[] array = new byte[payload_len]; if (has_mask) { - byte m0 = src.getByte(); - byte m1 = src.getByte(); - byte m2 = src.getByte(); - byte m3 = src.getByte(); - src.getBytes(array); + byte m0 = src.readByte(); + byte m1 = src.readByte(); + byte m2 = src.readByte(); + byte m3 = src.readByte(); + src.readBytes(array); int len = array.length; int neat_len = (len >>> 2) << 2; for (int i = 0; i < neat_len; i += 4) { @@ -181,9 +171,9 @@ public Frame decode(Channel ch, ByteBuf src) throws IOException { } } } else { - src.getBytes(array); + src.readBytes(array); } - WebSocketFrame f = newWebSocketFrame(ch, opcode); + WebSocketFrame f = new WebSocketFrame(opcode); if (opcode == TYPE_TEXT) { f.setContent(new String(array, ch.getCharset())); } else if (opcode == TYPE_BINARY) { @@ -199,30 +189,25 @@ public ByteBuf encode(Channel ch, Frame frame) throws IOException { if (buf == null) { throw new IOException("null buf content"); } - buf.flip(); - int size = buf.limit() - MAX_HEADER_LENGTH; + int size = buf.writeIndex() - MAX_HEADER_LENGTH; byte mark_code = f.getMarkCode(); if (size < 126) { - buf.position(8); - buf.putByte(8, mark_code); - buf.putByte(9, (byte) size); + buf.readIndex(8); + buf.setByte(8, mark_code); + buf.setByte(9, (byte) size); } else if (size <= MAX_UNSIGNED_SHORT) { - buf.position(6); - buf.putByte(6, mark_code); - buf.putByte(7, (byte) 126); - buf.putShort(8, size); + buf.readIndex(6); + buf.setByte(6, mark_code); + buf.setByte(7, (byte) 126); + buf.setShort(8, size); } else { - buf.putByte(mark_code); - buf.putByte((byte) 127); - buf.putLong(size); + buf.writeByte(mark_code); + buf.writeByte((byte) 127); + buf.writeLong(size); } return buf; } - public int getFrameStackSize() { - return frameStackSize; - } - @Override public String getProtocolId() { return PROTOCOL_ID; @@ -233,36 +218,9 @@ public int getHeaderLength() { return MAX_HEADER_LENGTH; } - private WebSocketFrame newWebSocketFrame(Channel ch, byte opcode) { - if (frameStackSize > 0) { - // NioEventLoop eventLoop = ch.getEventLoop(); - // FixedThreadStack stack = (FixedThreadStack) eventLoop - // .getAttribute(FRAME_STACK_KEY); - // if (stack == null) { - // stack = new FixedThreadStack<>(frameStackSize); - // eventLoop.setAttribute(FRAME_STACK_KEY, stack); - // } - // WebSocketFrame frame = stack.pop(); - // if (frame == null) { - // return new WebSocketFrame(ch, limit); - // } - // return frame.reset(ch, limit); - } - return new WebSocketFrame(opcode); - } - @Override protected ByteBuf getPingBuf() { return PING.duplicate(); } - @SuppressWarnings("unchecked") - public void release(NioEventLoop eventLoop, Frame frame) { - //FIXME ..final stack is null or not null - List stack = (List) eventLoop.getAttribute(FRAME_STACK_KEY); - if (stack != null && stack.size() < frameStackSize) { - stack.add((WebSocketFrame) frame); - } - } - } diff --git a/firenio-codec/src/main/java/com/firenio/codec/http2/Http2Codec.java b/firenio-codec/src/main/java/com/firenio/codec/http2/Http2Codec.java index bb73e9ec6..56386fe8e 100644 --- a/firenio-codec/src/main/java/com/firenio/codec/http2/Http2Codec.java +++ b/firenio-codec/src/main/java/com/firenio/codec/http2/Http2Codec.java @@ -106,11 +106,11 @@ public class Http2Codec extends ProtocolCodec { public Frame decode(Channel ch, ByteBuf src) throws Exception { Http2Session session = (Http2Session) ch.getAttachment(); if (session.isPrefaceRead()) { - if (src.remaining() < PREFACE_BINARY.length) { + if (src.readableBytes() < PREFACE_BINARY.length) { return null; } for (int i = 0; i < PREFACE_BINARY.length; i++) { - if (src.getByte() != PREFACE_BINARY[i]) { + if (src.readByte() != PREFACE_BINARY[i]) { throw NOT_HTTP2_PROTOCL; } } @@ -122,19 +122,19 @@ public Frame decode(Channel ch, ByteBuf src) throws Exception { ch.writeAndFlush(f); return decode(ch, src); } - if (src.remaining() < PROTOCOL_HEADER) { + if (src.readableBytes() < PROTOCOL_HEADER) { return null; } - byte b0 = src.getByte(); - byte b1 = src.getByte(); - byte b2 = src.getByte(); - byte type = src.getByte(); - byte flags = src.getByte(); - int v = src.getInt(); + byte b0 = src.readByte(); + byte b1 = src.readByte(); + byte b2 = src.readByte(); + byte type = src.readByte(); + byte flags = src.readByte(); + int v = src.readInt(); int length = ((b0 & 0xff) << 8 * 2) | ((b1 & 0xff) << 8 * 1) | ((b2 & 0xff) << 8 * 0); int streamIdentifier = v & 0xFFFFFFFF; - if (src.remaining() < length) { - src.skip(-PROTOCOL_HEADER); + if (src.readableBytes() < length) { + src.skipRead(-PROTOCOL_HEADER); return null; } Http2FrameType hType = Http2FrameType.getValue(type & 0xff); @@ -191,14 +191,14 @@ public ByteBuf encode(Channel ch, Frame frame) { byte b1 = (byte) ((length >> 8 * 1) & 0xff); byte b0 = (byte) ((length >> 8 * 2) & 0xff); byte b3 = frameType.getByteValue(); - buf.putByte(b0); - buf.putByte(b1); - buf.putByte(b2); - buf.putByte(b3); - buf.putByte((byte) 0); - buf.putInt(f.getStreamIdentifier()); - buf.putBytes(payload); - return buf.flip(); + buf.writeByte(b0); + buf.writeByte(b1); + buf.writeByte(b2); + buf.writeByte(b3); + buf.writeByte((byte) 0); + buf.writeInt(f.getStreamIdentifier()); + buf.writeBytes(payload); + return buf; } private Http2Frame genFrame(Http2Session session, ByteBuf src, Http2FrameType type, int length, int streamIdentifier, byte flags) { @@ -215,16 +215,16 @@ private Http2Frame genFrame(Http2Session session, ByteBuf src, Http2FrameType ty fh.setStreamIdentifier(streamIdentifier); fh.setEndStream((flags & FLAG_END_STREAM) > 0); if ((flags & FLAG_PADDED) > 0) { - fh.setPadLength(src.getByte()); + fh.setPadLength(src.readByte()); } int streamDependency = 0; if ((flags & FLAG_PRIORITY) > 0) { - streamDependency = src.getInt(); + streamDependency = src.readInt(); boolean e = streamDependency < 0; if (e) { streamDependency = streamDependency & 0x7FFFFFFF; } - short weight = src.getUnsignedByte(); + short weight = src.readUnsignedByte(); fh.setE(e); fh.setStreamDependency(streamDependency); fh.setWeight(weight); @@ -245,8 +245,8 @@ private Http2Frame genFrame(Http2Session session, ByteBuf src, Http2FrameType ty fs.setStreamIdentifier(streamIdentifier); int settings = length / 6; for (int i = 0; i < settings; i++) { - int key = src.getShort(); - int value = src.getInt(); + int key = src.readShort(); + int value = src.readInt(); session.setSettings(key, value); } fs.setSettings(session.getSettings()); @@ -255,7 +255,7 @@ private Http2Frame genFrame(Http2Session session, ByteBuf src, Http2FrameType ty Http2WindowUpdateFrame fw = new Http2WindowUpdateFrame(); fw.setFlags(flags); fw.setStreamIdentifier(streamIdentifier); - fw.setUpdateValue(ByteUtil.getInt31(src.getInt())); + fw.setUpdateValue(ByteUtil.getInt31(src.readInt())); return fw; default: break; diff --git a/firenio-codec/src/main/java/com/firenio/codec/lengthvalue/LengthValueCodec.java b/firenio-codec/src/main/java/com/firenio/codec/lengthvalue/LengthValueCodec.java index de056b40d..6fc23daf0 100644 --- a/firenio-codec/src/main/java/com/firenio/codec/lengthvalue/LengthValueCodec.java +++ b/firenio-codec/src/main/java/com/firenio/codec/lengthvalue/LengthValueCodec.java @@ -52,12 +52,10 @@ public final class LengthValueCodec extends ProtocolCodec { static final int PROTOCOL_PONG = -2; static { - PING = ByteBuf.direct(4); - PONG = ByteBuf.direct(4); - PING.putInt(PROTOCOL_PING); - PONG.putInt(PROTOCOL_PONG); - PING.flip(); - PONG.flip(); + PING = ByteBuf.buffer(4); + PONG = ByteBuf.buffer(4); + PING.writeInt(PROTOCOL_PING); + PONG.writeInt(PROTOCOL_PONG); } private int limit; @@ -72,22 +70,22 @@ public LengthValueCodec(int limit) { @Override public Frame decode(Channel ch, ByteBuf src) throws IOException { - if (src.remaining() < PROTOCOL_HEADER) { + if (src.readableBytes() < PROTOCOL_HEADER) { return null; } - int len = src.getInt(); + int len = src.readInt(); if (len < 0) { return decode_ping(ch, len); } if (len > limit) { throw OVER_LIMIT; } - if (len > src.remaining()) { - src.skip(-PROTOCOL_HEADER); + if (len > src.readableBytes()) { + src.skipRead(-PROTOCOL_HEADER); return null; } byte[] data = new byte[len]; - src.getBytes(data); + src.readBytes(data); return new LengthValueFrame(new String(data, ch.getCharset())); } @@ -110,8 +108,8 @@ protected ByteBuf getPingBuf() { @Override public ByteBuf encode(Channel ch, Frame frame) { - ByteBuf buf = frame.getBufContent().flip(); - buf.putInt(0, buf.limit() - PROTOCOL_HEADER); + ByteBuf buf = frame.getBufContent(); + buf.setInt(0, buf.writeIndex() - PROTOCOL_HEADER); return buf; } diff --git a/firenio-codec/src/main/java/com/firenio/codec/lengthvalue/LengthValueFrame.java b/firenio-codec/src/main/java/com/firenio/codec/lengthvalue/LengthValueFrame.java index 75ce36e20..d7b451ffa 100644 --- a/firenio-codec/src/main/java/com/firenio/codec/lengthvalue/LengthValueFrame.java +++ b/firenio-codec/src/main/java/com/firenio/codec/lengthvalue/LengthValueFrame.java @@ -24,9 +24,4 @@ public LengthValueFrame() {} public LengthValueFrame(String content) { this.setContent(content); } - - public String toString() { - return getStringContent(); - } - } diff --git a/firenio-codec/src/main/java/com/firenio/codec/protobase/ProtobaseCodec.java b/firenio-codec/src/main/java/com/firenio/codec/protobase/ProtobaseCodec.java index ae889d243..ab36c0706 100644 --- a/firenio-codec/src/main/java/com/firenio/codec/protobase/ProtobaseCodec.java +++ b/firenio-codec/src/main/java/com/firenio/codec/protobase/ProtobaseCodec.java @@ -37,7 +37,7 @@ public final class ProtobaseCodec extends ProtocolCodec { public static final IOException ILLEGAL_PROTOCOL = EXCEPTION("illegal protocol"); - public static final IOException OVER_LIMIT = EXCEPTION("over limit"); + public static final IOException OVER_LIMIT = EXCEPTION("over writeIndex"); static final ByteBuf PING; static final ByteBuf PONG; static final int PROTOCOL_HEADER = 12; @@ -46,12 +46,10 @@ public final class ProtobaseCodec extends ProtocolCodec { static final int PROTOCOL_PONG_MASK = 0b1100_0000; static { - PING = ByteBuf.direct(4); - PONG = ByteBuf.direct(4); - PING.putInt(PROTOCOL_PING << 24); - PONG.putInt(PROTOCOL_PONG << 24); - PING.flip(); - PONG.flip(); + PING = ByteBuf.buffer(4); + PONG = ByteBuf.buffer(4); + PING.writeInt(PROTOCOL_PING << 24); + PONG.writeInt(PROTOCOL_PONG << 24); } private final int limit; @@ -66,25 +64,25 @@ public ProtobaseCodec(int limit) { @Override public Frame decode(Channel ch, ByteBuf src) throws IOException { - if (src.remaining() < 4) { + if (src.readableBytes() < 4) { return null; } - byte flags = src.absByte(src.absPos()); - int len = src.getInt() & 0xffffff; + byte flags = src.getByteAbs(src.absReadIndex()); + int len = src.readInt() & 0xffffff; if (flags < 0) { return decode_ping(ch, flags); } if (len > limit) { throw OVER_LIMIT; } - if (len > src.remaining()) { - src.skip(-4); + if (len > src.readableBytes()) { + src.skipRead(-4); return null; } - int frameId = src.getInt(); - int channelId = src.getInt(); + int frameId = src.readInt(); + int channelId = src.readInt(); byte[] data = new byte[len - 8]; - src.getBytes(data); + src.readBytes(data); ProtobaseFrame f = new ProtobaseFrame(); f.setFlags(flags); f.setChannelId(channelId); @@ -118,10 +116,10 @@ protected ByteBuf getPingBuf() { @Override public ByteBuf encode(Channel ch, Frame frame) { ProtobaseFrame f = (ProtobaseFrame) frame; - ByteBuf buf = f.getBufContent().flip(); - buf.putInt(0, (buf.limit() - 4) | (f.getFlags() << 24)); - buf.putInt(4, f.getFrameId()); - buf.putInt(8, f.getChannelId()); + ByteBuf buf = f.getBufContent(); + buf.setInt(0, (buf.writeIndex() - 4) | (f.getFlags() << 24)); + buf.setInt(4, f.getFrameId()); + buf.setInt(8, f.getChannelId()); return buf; } diff --git a/firenio-core/pom.xml b/firenio-core/pom.xml index a6a35a894..c8b4921ea 100644 --- a/firenio-core/pom.xml +++ b/firenio-core/pom.xml @@ -10,7 +10,7 @@ com.firenio firenio - 1.2.2 + 1.3.2 ../firenio/pom.xml @@ -19,7 +19,7 @@ org.wildfly.openssl wildfly-openssl-java - 1.0.6.Final + 1.0.8.Final provided diff --git a/firenio-core/src/main/java/com/firenio/Develop.java b/firenio-core/src/main/java/com/firenio/Develop.java index 9ccc6f734..425b3d239 100644 --- a/firenio-core/src/main/java/com/firenio/Develop.java +++ b/firenio-core/src/main/java/com/firenio/Develop.java @@ -22,11 +22,13 @@ */ public class Develop { - public static final boolean BUF_DEBUG = DevelopConfig.BUF_DEBUG; - public static final boolean EPOLL_DEBUG = DevelopConfig.EPOLL_DEBUG; - public static final String EPOLL_PATH = DevelopConfig.EPOLL_PATH; - public static final boolean NATIVE_DEBUG = DevelopConfig.NATIVE_DEBUG; - public static final boolean DEBUG_ERROR = Options.isDebugError(); + public static final boolean BUF_DEBUG = DevelopConfig.BUF_DEBUG; + public static final boolean SSL_DEBUG = DevelopConfig.SSL_DEBUG; + public static final boolean EPOLL_DEBUG = DevelopConfig.EPOLL_DEBUG; + public static final String EPOLL_PATH = DevelopConfig.EPOLL_PATH; + public static final boolean NATIVE_DEBUG = DevelopConfig.NATIVE_DEBUG; + public static final boolean CHANNEL_DEBUG = DevelopConfig.CHANNEL_DEBUG; + public static final boolean DEBUG_ERROR = Options.isDebugError(); public static void debugException(Logger logger, Throwable e) { if (DEBUG_ERROR) { diff --git a/firenio-core/src/main/java/com/firenio/DevelopConfig.java b/firenio-core/src/main/java/com/firenio/DevelopConfig.java index b1015b7b5..3dd960146 100644 --- a/firenio-core/src/main/java/com/firenio/DevelopConfig.java +++ b/firenio-core/src/main/java/com/firenio/DevelopConfig.java @@ -20,10 +20,12 @@ */ public class DevelopConfig { - public static boolean BUF_DEBUG = false; - public static boolean EPOLL_DEBUG = false; - public static String EPOLL_PATH = "/home/test/git-rep/firenio/firenio-epoll/obj/native.o"; - public static boolean NATIVE_DEBUG = false; + public static boolean BUF_DEBUG = false; + public static boolean SSL_DEBUG = false; + public static boolean EPOLL_DEBUG = false; + public static String EPOLL_PATH = "/home/test/git-rep/firenio/firenio-epoll/obj/native.o"; + public static boolean NATIVE_DEBUG = false; + public static boolean CHANNEL_DEBUG = false; } diff --git a/firenio-core/src/main/java/com/firenio/LifeCycle.java b/firenio-core/src/main/java/com/firenio/LifeCycle.java index c64b102e4..3603ad931 100644 --- a/firenio-core/src/main/java/com/firenio/LifeCycle.java +++ b/firenio-core/src/main/java/com/firenio/LifeCycle.java @@ -49,7 +49,7 @@ protected void checkNotRunning() { protected abstract void doStop(); - private void fireEvent(int event, Exception exception) { + private void fireEvent(int event, Throwable exception) { if (lifeCycleListeners.size() == 0) { return; } @@ -57,7 +57,7 @@ private void fireEvent(int event, Exception exception) { for (LifeCycleListener listener : lifeCycleListeners) { try { listener.lifeCycleStarting(this); - } catch (Exception e) { + } catch (Throwable e) { logger.error(e.getMessage(), e); } } @@ -65,7 +65,7 @@ private void fireEvent(int event, Exception exception) { for (LifeCycleListener listener : lifeCycleListeners) { try { listener.lifeCycleStarted(this); - } catch (Exception e) { + } catch (Throwable e) { logger.error(e.getMessage(), e); } } @@ -73,7 +73,7 @@ private void fireEvent(int event, Exception exception) { for (LifeCycleListener listener : lifeCycleListeners) { try { listener.lifeCycleStopping(this); - } catch (Exception e) { + } catch (Throwable e) { logger.error(e.getMessage(), e); } } @@ -81,7 +81,7 @@ private void fireEvent(int event, Exception exception) { for (LifeCycleListener listener : lifeCycleListeners) { try { listener.lifeCycleStopped(this); - } catch (Exception e) { + } catch (Throwable e) { logger.error(e.getMessage(), e); } } @@ -89,7 +89,7 @@ private void fireEvent(int event, Exception exception) { for (LifeCycleListener listener : lifeCycleListeners) { try { listener.lifeCycleFailure(this, exception); - } catch (Exception e) { + } catch (Throwable e) { logger.error(e.getMessage(), e); } } @@ -130,7 +130,7 @@ public synchronized void start() throws Exception { this.doStart(); this.state = RUNNING; this.onStarted(); - } catch (Exception e) { + } catch (Throwable e) { Util.stop(this); this.state = FAILED; this.fireEvent(state, e); @@ -153,7 +153,7 @@ public synchronized void stop() { } try { this.doStop(); - } catch (Exception e) { + } catch (Throwable e) { logger.error(e.getMessage(), e); } this.state = STOPPED; diff --git a/firenio-core/src/main/java/com/firenio/LifeCycleListener.java b/firenio-core/src/main/java/com/firenio/LifeCycleListener.java index a8cd40dc0..9ea527361 100644 --- a/firenio-core/src/main/java/com/firenio/LifeCycleListener.java +++ b/firenio-core/src/main/java/com/firenio/LifeCycleListener.java @@ -22,7 +22,7 @@ public int compareTo(LifeCycleListener o) { return sortIndex() - o.sortIndex(); } - public void lifeCycleFailure(LifeCycle lifeCycle, Exception exception) {} + public void lifeCycleFailure(LifeCycle lifeCycle, Throwable exception) {} public void lifeCycleStarted(LifeCycle lifeCycle) {} diff --git a/firenio-core/src/main/java/com/firenio/Options.java b/firenio-core/src/main/java/com/firenio/Options.java index 0d2e196ec..73aa80653 100644 --- a/firenio-core/src/main/java/com/firenio/Options.java +++ b/firenio-core/src/main/java/com/firenio/Options.java @@ -16,7 +16,6 @@ package com.firenio; import com.firenio.common.Util; -import com.firenio.component.Native; /** * @author wangkai @@ -28,6 +27,7 @@ public class Options { static final String BUF_RECYCLE = "com.firenio.bufRecycle"; static final String CHANNEL_READ_FIRST = "com.firenio.channelReadFirst"; static final String DEBUG_ERROR = "com.firenio.debugError"; + static final String ENABLE_UNSAFE = "com.firenio.enableUnsafe"; static final String ENABLE_EPOLL = "com.firenio.ssl.enableEpoll"; static final String ENABLE_OPENSSL = "com.firenio.ssl.enableOpenSsl"; static final String ENABLE_UNSAFE_BUF = "com.firenio.ssl.enableUnsafeBuf"; @@ -36,7 +36,7 @@ public class Options { static final String SYS_CLOCK_STEP = "com.firenio.sysClockStep"; public static boolean isDebugError() { - return Util.getBooleanProperty(DEBUG_ERROR); + return isTrue(DEBUG_ERROR); } public static String getOpensslPath() { @@ -44,39 +44,43 @@ public static String getOpensslPath() { } public static int getSslUnwrapBufferSize(int defaultValue) { - return Util.getIntProperty(SSL_UNWRAP_BUFFER_SIZE, defaultValue); + return getInt(SSL_UNWRAP_BUFFER_SIZE, defaultValue); } - public static long getSysClockStep() { - return Util.getIntProperty(SYS_CLOCK_STEP); + public static int getSysClockStep() { + return getInt(SYS_CLOCK_STEP); } public static boolean isBufAutoExpansion() { - return Util.getBooleanProperty(BUF_AUTO_EXPANSION, true); + return isTrue(BUF_AUTO_EXPANSION, true); } public static boolean isBufThreadYield() { - return Util.getBooleanProperty(BUF_THREAD_YIELD, false); + return isTrue(BUF_THREAD_YIELD, false); } public static boolean isBufRecycle() { - return Util.getBooleanProperty(BUF_RECYCLE); + return isTrue(BUF_RECYCLE); } public static boolean isChannelReadFirst() { - return Util.getBooleanProperty(CHANNEL_READ_FIRST); + return isTrue(CHANNEL_READ_FIRST); + } + + public static boolean isEnableUnsafe() { + return isTrue(ENABLE_UNSAFE, true); } public static boolean isEnableEpoll() { - return Util.getBooleanProperty(ENABLE_EPOLL); + return isTrue(ENABLE_EPOLL, true); } public static boolean isEnableOpenssl() { - return Util.getBooleanProperty(ENABLE_OPENSSL); + return isTrue(ENABLE_OPENSSL); } public static boolean isEnableUnsafeBuf() { - return Native.EPOLL_AVAILABLE && Util.getBooleanProperty(ENABLE_UNSAFE_BUF); + return isTrue(ENABLE_UNSAFE_BUF); } public static void setBufAutoExpansion(boolean auto) { @@ -84,31 +88,39 @@ public static void setBufAutoExpansion(boolean auto) { } public static void setBufThreadYield(boolean yield) { - System.setProperty(BUF_THREAD_YIELD, String.valueOf(yield)); + setBool(BUF_THREAD_YIELD, yield); } + // NOTICE: DO NOT USE public static void setBufRecycle(boolean recycle) { - System.setProperty(BUF_RECYCLE, String.valueOf(recycle)); + if (recycle){ + throw new RuntimeException("do not use BufRecycle"); + } + setBool(BUF_RECYCLE, recycle); } public static void setChannelReadFirst(boolean channelReadFirst) { - System.setProperty(CHANNEL_READ_FIRST, String.valueOf(channelReadFirst)); + setBool(CHANNEL_READ_FIRST, channelReadFirst); } public static void setDebugError(boolean debugError) { - System.setProperty(DEBUG_ERROR, String.valueOf(debugError)); + setBool(DEBUG_ERROR, debugError); + } + + public static void setEnableUnsafe(boolean enable) { + setBool(ENABLE_UNSAFE, enable); } public static void setEnableEpoll(boolean enable) { - System.setProperty(ENABLE_EPOLL, String.valueOf(enable)); + setBool(ENABLE_EPOLL, enable); } public static void setEnableOpenssl(boolean enable) { - System.setProperty(ENABLE_OPENSSL, String.valueOf(enable)); + setBool(ENABLE_OPENSSL, enable); } public static void setEnableUnsafeBuf(boolean enable) { - System.setProperty(ENABLE_UNSAFE_BUF, String.valueOf(enable)); + setBool(ENABLE_UNSAFE_BUF, enable); } public static void setOpensslPath(String path) { @@ -116,11 +128,43 @@ public static void setOpensslPath(String path) { } public static void setSslUnwrapBufferSize(int size) { - System.setProperty(SSL_UNWRAP_BUFFER_SIZE, String.valueOf(size)); + setInt(SSL_UNWRAP_BUFFER_SIZE, size); } public static void setSysClockStep(int step) { - System.setProperty(SYS_CLOCK_STEP, String.valueOf(step)); + setInt(SYS_CLOCK_STEP, step); + } + + private static boolean isTrue(String key) { + return isTrue(key, false); + } + + private static boolean isTrue(String key, boolean def) { + String v = Util.getStringProperty(key); + if (Util.isNullOrBlank(v)) { + return def; + } + return "1".equals(v) || "true".equals(v); + } + + private static void setBool(String key) { + setBool(key, false); + } + + private static void setBool(String key, boolean value) { + setInt(key, value ? 1 : 0); + } + + private static int getInt(String key) { + return Util.getIntProperty(key); + } + + private static int getInt(String key, int def) { + return Util.getIntProperty(key, def); + } + + private static void setInt(String key, int value) { + System.setProperty(key, String.valueOf(value)); } } diff --git a/firenio-core/src/main/java/com/firenio/buffer/ByteBuf.java b/firenio-core/src/main/java/com/firenio/buffer/ByteBuf.java index 14945d0e8..5c9ac1d6e 100644 --- a/firenio-core/src/main/java/com/firenio/buffer/ByteBuf.java +++ b/firenio-core/src/main/java/com/firenio/buffer/ByteBuf.java @@ -36,24 +36,53 @@ public abstract class ByteBuf implements Releasable { protected volatile int referenceCount = 0; - static void copy(byte[] src, int srcPos, byte[] dst, int dstPos, int len) { - System.arraycopy(src, srcPos, dst, dstPos, len); + protected int offset; + protected int abs_write_index; + protected int abs_read_index; + protected int marked_abs_write_index; + protected int marked_abs_read_index; + + public static ByteBuf direct(int cap) { + return wrap(Unsafe.allocateDirectByteBuffer(cap)); } - static void copy(byte[] src, int srcPos, long dst, int len) { - Unsafe.copyFromArray(src, srcPos, dst, len); + public static ByteBuf buffer(int cap) { + if (Unsafe.UNSAFE_BUF_AVAILABLE) { + return unsafe(cap); + } else { + if (Unsafe.DIRECT_BUFFER_AVAILABLE) { + return direct(cap); + } else { + return heap(cap); + } + } } - static void copy(long src, byte[] dst, int dstPos, int len) { - Unsafe.copyToArray(src, dst, dstPos, len); + public static ByteBuf unsafe(int cap) { + return new UnpooledUnsafeByteBuf(Unsafe.allocate(cap), cap); } - static void copy(long src, long dst, int len) { - Unsafe.copyMemory(src, dst, len); + public static ByteBuf wrapAuto(byte[] data) { + return wrapAuto(data, 0, data.length); } - public static ByteBuf direct(int cap) { - return wrap(Unsafe.allocateDirectByteBuffer(cap)); + public static ByteBuf wrapAuto(byte[] data, int off, int len) { + if (preferHeap()) { + return wrap(data, off, len); + } + ByteBuf buf = buffer(len); + buf.writeBytes(data, off, len); + return buf; + } + + public static ByteBuf wrapUnsafe(byte[] data) { + return wrapUnsafe(data, 0, data.length); + } + + public static ByteBuf wrapUnsafe(byte[] data, int off, int len) { + ByteBuf buf = unsafe(len); + buf.writeBytes(data, off, len); + return buf; } public static ByteBuf empty() { @@ -80,25 +109,45 @@ public static ByteBuf wrap(ByteBuffer buffer) { } } - public abstract byte absByte(int pos); + public static ByteBuf wrap(long address, int cap) { + return new UnpooledUnsafeByteBuf(address, cap); + } - public abstract int absLimit(); + public abstract byte getByteAbs(int pos); - public abstract ByteBuf absLimit(int limit); + public int absWriteIndex() { + return abs_write_index; + } - public abstract int absPos(); + public ByteBuf absWriteIndex(int index) { + this.abs_write_index = index; + return this; + } + + public int absReadIndex() { + return abs_read_index; + } - public abstract ByteBuf absPos(int absPos); + public ByteBuf absReadIndex(int index) { + this.abs_read_index = index; + return this; + } - protected void addReferenceCount() { + public boolean retain() { int referenceCount = this.referenceCount; + if (referenceCount == 0) { + return false; + } if (refCntUpdater.compareAndSet(this, referenceCount, referenceCount + 1)) { - return; + return true; } for (; ; ) { referenceCount = this.referenceCount; + if (referenceCount == 0) { + return false; + } if (refCntUpdater.compareAndSet(this, referenceCount, referenceCount + 1)) { - break; + return true; } else { if (BUF_THREAD_YIELD) { Thread.yield(); @@ -113,14 +162,20 @@ protected void addReferenceCount() { public abstract int capacity(); + public abstract void compact(); + protected void capacity(int cap) {} - public abstract ByteBuf clear(); + public ByteBuf clear() { + abs_read_index = 0; + abs_write_index = 0; + return this; + } public abstract ByteBuf duplicate(); final void ensureWritable(int len) { - if (AUTO_EXPANSION && len > remaining()) { + if (AUTO_EXPANSION && len > writableBytes()) { int cap = capacity(); int wantCap = capacity() + len; int newCap = cap + (cap >> 1); @@ -133,149 +188,196 @@ final void ensureWritable(int len) { public abstract void expansion(int cap); - public abstract ByteBuf flip(); - - protected abstract int get0(ByteBuffer dst, int len); - - public abstract byte getByte(); + public abstract byte readByte(); public abstract byte getByte(int index); - public byte[] getBytes() { - return getBytes(remaining()); - } - public void getBytes(byte[] dst) { - getBytes(dst, 0, dst.length); + public byte[] getBytes(int index) { + return getBytes(index, readableBytes()); } - public abstract void getBytes(byte[] dst, int offset, int length); + public byte[] getBytes(int index, int length) { + byte[] bytes = new byte[length]; + getBytes(index, bytes); + return bytes; + } - public int getBytes(ByteBuf dst) { - return dst.putBytes(this, dst.remaining()); + public void getBytes(int index, byte[] dst) { + getBytes(index, dst, 0, dst.length); } - public int getBytes(ByteBuf dst, int length) { - return dst.putBytes(this, length); + public abstract void getBytes(int index, byte[] dst, int offset, int length); + + public int getBytes(int index, ByteBuf dst) { + return getBytes(index, dst, dst.writableBytes()); } - public int getBytes(ByteBuffer dst) { - int len = Math.min(remaining(), dst.remaining()); + public int getBytes(int index, ByteBuf dst, int length) { + int len = Math.min(readableBytes(), length); if (len == 0) { return 0; } - return get0(dst, len); + return getBytes0(index, dst, len); + } + + public int getBytes(int index, ByteBuffer dst) { + return getBytes(index, dst, dst.remaining()); } - public int getBytes(ByteBuffer dst, int length) { - int len = Math.min(remaining(), dst.remaining()); - len = Math.min(len, length); + public int getBytes(int index, ByteBuffer dst, int length) { + int len = Math.min(readableBytes(), length); if (len == 0) { return 0; } - return get0(dst, len); + return getBytes0(index, dst, len); } - public byte[] getBytes(int length) { + protected abstract int getBytes0(int index, ByteBuf dst, int len); + + protected abstract int getBytes0(int index, ByteBuffer dst, int len); + + + public byte[] readBytes() { + return readBytes(readableBytes()); + } + + public byte[] readBytes(int length) { byte[] bytes = new byte[length]; - getBytes(bytes); + readBytes(bytes); return bytes; } - public abstract int getInt(); + public void readBytes(byte[] dst) { + readBytes(dst, 0, dst.length); + } + + public abstract void readBytes(byte[] dst, int offset, int length); + + public int readBytes(ByteBuf dst) { + return readBytes(dst, dst.writableBytes()); + } + + public int readBytes(ByteBuf dst, int length) { + int len = Math.min(readableBytes(), length); + if (len == 0) { + return 0; + } + return readBytes0(dst, len); + } + + public int readBytes(ByteBuffer dst) { + return readBytes(dst, dst.remaining()); + } + + public int readBytes(ByteBuffer dst, int length) { + int len = Math.min(readableBytes(), length); + if (len == 0) { + return 0; + } + return readBytes0(dst, len); + } + + protected abstract int readBytes0(ByteBuf dst, int len); + + protected abstract int readBytes0(ByteBuffer dst, int len); + + public abstract int readInt(); public abstract int getInt(int index); - public abstract int getIntLE(); + public abstract int readIntLE(); public abstract int getIntLE(int index); - public abstract long getLong(); + public abstract long readLong(); public abstract long getLong(int index); - public abstract long getLongLE(); + public abstract long readLongLE(); public abstract long getLongLE(int index); - public float getFloat() { - return Float.intBitsToFloat(getInt()); + public float readFloat() { + return Float.intBitsToFloat(readInt()); } public float getFloat(int index) { return Float.intBitsToFloat(getInt(index)); } - public float getFloatLE() { - return Float.intBitsToFloat(getIntLE()); + public float readFloatLE() { + return Float.intBitsToFloat(readIntLE()); } public float getFloatLE(int index) { return Float.intBitsToFloat(getIntLE(index)); } - public double getDouble() { - return Double.longBitsToDouble(getLong()); + public double readDouble() { + return Double.longBitsToDouble(readLong()); } public double getDouble(int index) { return Double.longBitsToDouble(getLong(index)); } - public double getDoubleLE() { - return Double.longBitsToDouble(getLongLE()); + public double readDoubleLE() { + return Double.longBitsToDouble(readLongLE()); } public double getDoubleLE(int index) { return Double.longBitsToDouble(getLongLE(index)); } - public abstract ByteBuffer getNioBuffer(); + protected abstract ByteBuffer getNioBuffer(); - public abstract short getShort(); + public abstract short readShort(); public abstract short getShort(int index); - public abstract short getShortLE(); + public abstract short readShortLE(); public abstract short getShortLE(int index); - public abstract short getUnsignedByte(); + public abstract short readUnsignedByte(); public abstract short getUnsignedByte(int index); - public abstract long getUnsignedInt(); + public abstract long readUnsignedInt(); public abstract long getUnsignedInt(int index); - public abstract long getUnsignedIntLE(); + public abstract long readUnsignedIntLE(); public abstract long getUnsignedIntLE(int index); - public abstract int getUnsignedShort(); + public abstract int readUnsignedShort(); public abstract int getUnsignedShort(int index); - public abstract int getUnsignedShortLE(); + public abstract int readUnsignedShortLE(); public abstract int getUnsignedShortLE(int index); public abstract boolean hasArray(); - public abstract boolean hasRemaining(); + public boolean hasReadableBytes() { + return absReadIndex() < absWriteIndex(); + } public int indexOf(byte b) { - return indexOf(b, absPos(), remaining()); + return indexOf(b, absReadIndex(), readableBytes()); } public int indexOf(byte b, int size) { - return indexOf(b, absPos(), size); + return indexOf(b, absReadIndex(), size); } public abstract int indexOf(byte b, int absPos, int size); - public boolean isFullLimit(){ - return limit() == capacity(); + public boolean hasWritableBytes() { + return writableBytes() > 0; } public abstract boolean isPooled(); @@ -290,225 +392,264 @@ protected int ix(int index) { } public int lastIndexOf(byte b) { - return lastIndexOf(b, absLimit() - 1, remaining()); + return lastIndexOf(b, absWriteIndex() - 1, readableBytes()); } public int lastIndexOf(byte b, int size) { - return lastIndexOf(b, absLimit() - 1, size); + return lastIndexOf(b, absWriteIndex() - 1, size); } public abstract int lastIndexOf(byte b, int absPos, int size); - //---------------------------------put byte---------------------------------// - - public abstract int limit(); - - public abstract ByteBuf limit(int limit); - - public abstract ByteBuf markL(); + public int writeIndex() { + return absWriteIndex() - offset(); + } - //---------------------------------put bytes---------------------------------// + public ByteBuf writeIndex(int index) { + this.abs_write_index = ix(index); + return this; + } - public abstract ByteBuf markP(); + public ByteBuf markWriteIndex() { + this.marked_abs_write_index = absWriteIndex(); + return this; + } - public abstract ByteBuffer nioBuffer(); + public ByteBuf markReadIndex() { + this.marked_abs_read_index = this.abs_read_index; + return this; + } - protected int offset() { - return 0; + public int offset() { + return offset; } - protected void offset(int offset) {} + protected void offset(int offset) { + this.offset = offset; + } - public abstract int position(); + public int readIndex() { + return absReadIndex() - offset(); + } - public abstract ByteBuf position(int position); + public ByteBuf readIndex(int index) { + this.abs_read_index = ix(index); + return this; + } - protected ByteBuf produce(int unitOffset, int unitEnd) { + protected ByteBuf produce(int unitOffset, int unitSize) { return this; } - public void putByte(byte b) { + public void writeByte(byte b) { ensureWritable(1); - putByte0(b); + writeByte0(b); } - public abstract void putByte(int index, byte b); + public abstract void setByte(int index, byte b); - protected abstract void putByte0(byte b); + protected abstract void writeByte0(byte b); - public void putBytes(byte[] src) { - putBytes(src, 0, src.length); + public void setBytes(int index, byte[] src) { + setBytes(index, src, 0, src.length); } - //---------------------------------put int---------------------------------// - - public int putBytes(byte[] src, int offset, int length) { + public int setBytes(int index, byte[] src, int offset, int length) { if (AUTO_EXPANSION) { ensureWritable(length); - return putBytes0(src, offset, length); + return setBytes0(index, src, offset, length); } else { - if (!hasRemaining()) { + int len = Math.min(writableBytes(), length); + if (len == 0) { return 0; } - return putBytes0(src, offset, Math.min(remaining(), length)); + return setBytes0(index, src, offset, length); } } - public int putBytes(ByteBuf src) { - int len = src.remaining(); - if (len == 0) { - return 0; - } - return putBytes0(src, len); + protected abstract int setBytes0(int index, byte[] src, int offset, int length); + + public int setBytes(int index, ByteBuf src) { + return setBytes(index, src, src.readableBytes()); } - public int putBytes(ByteBuf src, int length) { - int len = Math.min(length, src.remaining()); - if (len == 0) { - return 0; + public int setBytes(int index, ByteBuf src, int length) { + if (AUTO_EXPANSION) { + ensureWritable(length); + return setBytes0(index, src, length); + } else { + int len = Math.min(writableBytes(), length); + if (len == 0) { + return 0; + } + return setBytes0(index, src, len); } - return putBytes0(src, len); } - public int putBytes(ByteBuffer src) { - int len = src.remaining(); - if (len == 0) { - return 0; + public int setBytes(int index, ByteBuffer src) { + return setBytes(index, src, src.remaining()); + } + + public int setBytes(int index, ByteBuffer src, int length) { + if (AUTO_EXPANSION) { + ensureWritable(length); + return setBytes0(index, src, length); + } else { + int len = Math.min(writableBytes(), length); + if (len == 0) { + return 0; + } + return setBytes0(index, src, len); } - return putBytes0(src, len); } - public int putBytes(ByteBuffer src, int length) { - int len = Math.min(length, src.remaining()); - if (len == 0) { - return 0; + protected abstract int setBytes0(int index, ByteBuf src, int len); + + protected abstract int setBytes0(int index, ByteBuffer src, int len); + + + public void writeBytes(byte[] src) { + writeBytes(src, 0, src.length); + } + + public int writeBytes(byte[] src, int offset, int length) { + if (AUTO_EXPANSION) { + ensureWritable(length); + return writeBytes0(src, offset, length); + } else { + int len = Math.min(writableBytes(), length); + if (len == 0) { + return 0; + } + return writeBytes0(src, offset, length); } - return putBytes0(src, len); } - protected abstract int putBytes0(byte[] src, int offset, int length); + protected abstract int writeBytes0(byte[] src, int offset, int length); - //---------------------------------put long---------------------------------// + public int writeBytes(ByteBuf src) { + return writeBytes(src, src.readableBytes()); + } - protected int putBytes0(ByteBuf src, int len) { + public int writeBytes(ByteBuf src, int length) { if (AUTO_EXPANSION) { - ensureWritable(len); - return putBytes00(src, len); + ensureWritable(length); + return writeBytes0(src, length); } else { - if (!hasRemaining()) { + int len = Math.min(writableBytes(), length); + if (len == 0) { return 0; } - return putBytes00(src, Math.min(remaining(), len)); + return writeBytes0(src, len); } } - protected int putBytes0(ByteBuffer src, int len) { + public int writeBytes(ByteBuffer src) { + return writeBytes(src, src.remaining()); + } + + public int writeBytes(ByteBuffer src, int length) { if (AUTO_EXPANSION) { - ensureWritable(len); - return putBytes00(src, len); + ensureWritable(length); + return writeBytes0(src, length); } else { - if (!hasRemaining()) { + int len = Math.min(writableBytes(), length); + if (len == 0) { return 0; } - return putBytes00(src, Math.min(remaining(), len)); + return writeBytes0(src, len); } } - protected abstract int putBytes00(ByteBuf src, int len); + protected abstract int writeBytes0(ByteBuf src, int len); - protected abstract int putBytes00(ByteBuffer src, int len); + protected abstract int writeBytes0(ByteBuffer src, int len); - public void putInt(int value) { + public void writeInt(int value) { ensureWritable(4); - putInt0(value); + writeInt0(value); } - public abstract void putInt(int index, int value); - - //---------------------------------put double---------------------------------// + protected abstract void writeInt0(int value); - protected abstract void putInt0(int value); + public abstract void setInt(int index, int value); - public void putIntLE(int value) { + public void writeIntLE(int value) { ensureWritable(4); - putIntLE0(value); + writeIntLE0(value); } - public abstract void putIntLE(int index, int value); + protected abstract void writeIntLE0(int value); - protected abstract void putIntLE0(int value); + public abstract void setIntLE(int index, int value); - //---------------------------------put float---------------------------------// + public abstract void setLong(int index, long value); - public abstract void putLong(int index, long value); - - public void putLong(long value) { + public void writeLong(long value) { ensureWritable(8); - putLong0(value); + writeLong0(value); } - protected abstract void putLong0(long value); - - public abstract void putLongLE(int index, long value); + protected abstract void writeLong0(long value); - //---------------------------------put short---------------------------------// + public abstract void setLongLE(int index, long value); - public void putLongLE(long value) { + public void writeLongLE(long value) { ensureWritable(8); - putLongLE0(value); + writeLongLE0(value); } - protected abstract void putLongLE0(long value); + protected abstract void writeLongLE0(long value); - public void putDouble(int index, double value) { - putLong(index, Double.doubleToRawLongBits(value)); + public void setDouble(int index, double value) { + setLong(index, Double.doubleToRawLongBits(value)); } - public void putDouble(double value) { - putLong(Double.doubleToRawLongBits(value)); + public void writeDouble(double value) { + writeLong(Double.doubleToRawLongBits(value)); } - public void putDoubleLE(int index, double value) { - putLongLE(index, Double.doubleToRawLongBits(value)); + public void setDoubleLE(int index, double value) { + setLongLE(index, Double.doubleToRawLongBits(value)); } - public void putDoubleLE(double value) { - putLongLE(Double.doubleToRawLongBits(value)); + public void writeDoubleLE(double value) { + writeLongLE(Double.doubleToRawLongBits(value)); } - public void putFloat(int index, float value) { - putInt(index, Float.floatToRawIntBits(value)); + public void setFloat(int index, float value) { + setInt(index, Float.floatToRawIntBits(value)); } - public void putFloat(float value) { - putInt(Float.floatToRawIntBits(value)); + public void writeFloat(float value) { + writeInt(Float.floatToRawIntBits(value)); } - public void putFloatLE(int index, float value) { - putIntLE(index, Float.floatToRawIntBits(value)); + public void setFloatLE(int index, float value) { + setIntLE(index, Float.floatToRawIntBits(value)); } - public void putFloatLE(float value) { - putIntLE(Float.floatToRawIntBits(value)); + public void writeFloatLE(float value) { + writeIntLE(Float.floatToRawIntBits(value)); } - public void putShort(int value) { + public void writeShort(int value) { ensureWritable(2); - putShort0(value); + writeShort0(value); } - public abstract void putShort(int index, int value); + public abstract void setShort(int index, int value); - protected abstract void putShort0(int value); + protected abstract void writeShort0(int value); - public void putShortLE(int value) { + public void writeShortLE(int value) { ensureWritable(2); - putShortLE0(value); + writeShortLE0(value); } - public abstract void putShortLE(int index, int value); + public abstract void setShortLE(int index, int value); - protected abstract void putShortLE0(int value); + protected abstract void writeShortLE0(int value); @Override public final void release() { @@ -540,31 +681,95 @@ public final void release() { } } + public abstract ByteBuf reverseRead(); + + public abstract ByteBuf reverseWrite(); + + public ByteBuffer nioReadBuffer() { + ByteBuffer buffer = getNioBuffer(); + return (ByteBuffer) buffer.limit(absWriteIndex()).position(absReadIndex()); + } + + public ByteBuffer nioWriteBuffer() { + ByteBuffer buffer = getNioBuffer(); + return (ByteBuffer) buffer.limit(capacity() + offset()).position(absWriteIndex()); + } + protected abstract void release0(); - public abstract int remaining(); + public int readableBytes() { + return absWriteIndex() - absReadIndex(); + } - public abstract ByteBuf resetL(); + public void reset(byte[] memory) { + reset(memory, 0, memory.length); + } - public abstract ByteBuf resetP(); + public void reset(byte[] memory, int off, int len) { + throw unsupportedOperationException(); + } - public abstract ByteBuf reverse(); + public void reset(long memory, int capacity, int off, int len) { + throw unsupportedOperationException(); + } - public abstract ByteBuf skip(int length); + public void reset(ByteBuffer memory) { + throw unsupportedOperationException(); + } + + public int writableBytes() { + return capacity() - writeIndex(); + } + + public ByteBuf resetWriteIndex() { + this.abs_write_index = marked_abs_write_index; + return this; + } + + public ByteBuf resetReadIndex() { + this.abs_read_index = marked_abs_read_index; + return this; + } + + public int getMarkedReadIndex() { + return marked_abs_read_index - offset(); + } + + public int getMarkedWriteIndex() { + return marked_abs_write_index - offset(); + } + + public int getMarkedAbsReadIndex() { + return marked_abs_read_index; + } + + public int getMarkedAbsWriteIndex() { + return marked_abs_write_index; + } + + public ByteBuf skipRead(int length) { + this.abs_read_index += length; + return this; + } + + public ByteBuf skipWrite(int length) { + this.abs_write_index += length; + return this; + } @Override public String toString() { StringBuilder b = new StringBuilder(); b.append(getClass().getSimpleName()); - b.append("[pos="); - b.append(position()); - b.append(",lim="); - b.append(limit()); - b.append(",cap="); + b.append("[r="); + b.append(readIndex()); + b.append(",w="); + b.append(writeIndex()); + b.append(",c="); b.append(capacity()); - b.append(",remaining="); - b.append(remaining()); - b.append(",offset="); + b.append(",ra="); + b.append(readableBytes()); + b.append(",off="); b.append(offset()); b.append("]"); return b.toString(); @@ -572,9 +777,46 @@ public String toString() { protected int unitOffset() { return -1; - } protected void unitOffset(int unitOffset) {} + protected void recycleObject(){} + + UnsupportedOperationException unsupportedOperationException() { + return new UnsupportedOperationException(); + } + + public static boolean preferUnsafe() { + return Unsafe.UNSAFE_BUF_AVAILABLE; + } + + public static boolean preferDirect() { + return !preferUnsafe() && Unsafe.DIRECT_BUFFER_AVAILABLE; + } + + public static boolean preferHeap() { + return !preferUnsafe() && !Unsafe.DIRECT_BUFFER_AVAILABLE; + } + + static void copy(byte[] src, int srcPos, byte[] dst, int dstPos, int len) { + System.arraycopy(src, srcPos, dst, dstPos, len); + } + + static void copy(byte[] src, int srcPos, long dst, int len) { + Unsafe.copyFromArray(src, srcPos, dst, len); + } + + static void copy(long src, byte[] dst, int dstPos, int len) { + Unsafe.copyToArray(src, dst, dstPos, len); + } + + static void copy(long src, long dst, int len) { + Unsafe.copyMemory(src, dst, len); + } + + static long toUnsignedInt(int value) { + return value & 0xffffffffL; + } + } diff --git a/firenio-core/src/main/java/com/firenio/buffer/ByteBufAllocatorGroup.java b/firenio-core/src/main/java/com/firenio/buffer/ByteBufAllocatorGroup.java index c120d5ed5..33b23b3b9 100644 --- a/firenio-core/src/main/java/com/firenio/buffer/ByteBufAllocatorGroup.java +++ b/firenio-core/src/main/java/com/firenio/buffer/ByteBufAllocatorGroup.java @@ -93,7 +93,7 @@ public boolean isDirect() { public String[] toDebugString() { String[] res = new String[groupSize]; for (int i = 0; i < res.length; i++) { - res[i] = allocators[i].toString(); + res[i] = allocators[i].toDebugString(); } return res; } diff --git a/firenio-core/src/main/java/com/firenio/buffer/DirectByteBuf.java b/firenio-core/src/main/java/com/firenio/buffer/DirectByteBuf.java index 39cfd84e7..dec6f654b 100644 --- a/firenio-core/src/main/java/com/firenio/buffer/DirectByteBuf.java +++ b/firenio-core/src/main/java/com/firenio/buffer/DirectByteBuf.java @@ -19,132 +19,13 @@ import com.firenio.common.Unsafe; -abstract class DirectByteBuf extends ByteBuf { +abstract class DirectByteBuf extends UnsafeByteBuf { - protected int markLimit; protected ByteBuffer memory; DirectByteBuf(ByteBuffer memory) { - this.memory = memory; - } - - private static long toUnsignedInt(int value) { - if (value < 0) { - return value & 0xffffffffffffffffL; - } - return value; - } - - @Override - public byte absByte(int pos) { - return memory.get(pos); - } - - @Override - public int absLimit() { - return memory.limit(); - } - - @Override - public ByteBuf absLimit(int limit) { - this.memory.limit(limit); - return this; - } - - @Override - public int absPos() { - return memory.position(); - } - - @Override - public ByteBuf absPos(int pos) { - this.memory.position(pos); - return this; - } - - @Override - public byte[] array() { - throw new UnsupportedOperationException(); - } - - @Override - public ByteBuf clear() { - memory.position(offset()).limit(ix(capacity())); - return this; - } - - @Override - public ByteBuf flip() { - memory.limit(memory.position()); - memory.position(offset()); - return this; - } - - @Override - protected int get0(ByteBuffer dst, int len) { - if (dst.hasArray()) { - copy(address() + absPos(), dst.array(), dst.position(), len); - } else { - copy(address() + absPos(), Unsafe.address(dst) + dst.position(), len); - } - dst.position(dst.position() + len); - skip(len); - return len; - } - - @Override - public byte getByte() { - return memory.get(); - } - - @Override - public byte getByte(int index) { - return memory.get(ix(index)); - } - - @Override - public void getBytes(byte[] dst, int offset, int length) { - memory.get(dst, offset, length); - } - - @Override - public int getInt() { - return memory.getInt(); - } - - @Override - public int getInt(int index) { - return memory.getInt(ix(index)); - } - - @Override - public int getIntLE() { - return Integer.reverseBytes(memory.getInt()); - } - - @Override - public int getIntLE(int index) { - return Integer.reverseBytes(memory.getInt(ix(index))); - } - - @Override - public long getLong() { - return memory.getLong(); - } - - @Override - public long getLong(int index) { - return memory.getLong(ix(index)); - } - - @Override - public long getLongLE() { - return Long.reverseBytes(memory.getLong()); - } - - @Override - public long getLongLE(int index) { - return Long.reverseBytes(memory.getLong(ix(index))); + super(Unsafe.address(memory)); + this.setMemory(memory); } @Override @@ -152,315 +33,28 @@ public ByteBuffer getNioBuffer() { return memory; } - @Override - public short getShort() { - return memory.getShort(); - } - - @Override - public short getShort(int index) { - return memory.getShort(ix(index)); - } - - @Override - public short getShortLE() { - return Short.reverseBytes(memory.getShort()); - } - - @Override - public short getShortLE(int index) { - return Short.reverseBytes(memory.getShort(ix(index))); - } - - @Override - public short getUnsignedByte() { - return (short) (getByte() & 0xff); - } - - @Override - public short getUnsignedByte(int index) { - return (short) (getByte(index) & 0xff); - } - - @Override - public long getUnsignedInt() { - return toUnsignedInt(memory.getInt()); - } - - @Override - public long getUnsignedInt(int index) { - return toUnsignedInt(memory.getInt(ix(index))); - } - - @Override - public long getUnsignedIntLE() { - return toUnsignedInt(Integer.reverseBytes(memory.getInt())); - } - - @Override - public long getUnsignedIntLE(int index) { - return toUnsignedInt(Integer.reverseBytes(memory.getInt(ix(index)))); - } - - @Override - public int getUnsignedShort() { - return memory.getShort() & 0xffff; - } - - @Override - public int getUnsignedShort(int index) { - return memory.getShort(ix(index)) & 0xffff; - } - - @Override - public int getUnsignedShortLE() { - return Short.reverseBytes(memory.getShort()) & 0xffff; - } - - @Override - public int getUnsignedShortLE(int index) { - return Short.reverseBytes(memory.getShort(ix(index))) & 0xffff; - } - - @Override - public boolean hasArray() { - return false; - } - - @Override - public boolean hasRemaining() { - return memory.hasRemaining(); - } - - @Override - public int indexOf(byte b, int abs_pos, int size) { - ByteBuffer m = memory; - long addr = address(); - long p = addr + abs_pos; - long l = p + size; - for (; p < l; p++) { - if (Unsafe.getByte(p) == b) { - return (int) (p - addr); - } - } -// if (Unsafe.ENABLE) { -// long addr = address(); -// long p = addr + abs_pos; -// long l = p + size; -// for (; p < l; p++) { -// if (Unsafe.getByte(p) == b) { -// return (int) (p - addr); -// } -// } -// } else { -// int p = abs_pos; -// int l = p + size; -// for (; p < l; p++) { -// if (m.get(p) == b) { -// return p; -// } -// } -// } - return -1; - } - - @Override - public int lastIndexOf(byte b, int abs_pos, int size) { - ByteBuffer m = memory; - long addr = address(); - long p = addr + abs_pos; - long l = p - size - 1; - for (; p > l; p--) { - if (Unsafe.getByte(p) == b) { - return (int) (p - addr); - } - } -// if (Unsafe.ENABLE) { -// long addr = address(); -// long p = addr + abs_pos; -// long l = p - size - 1; -// for (; p > l; p--) { -// if (Unsafe.getByte(p) == b) { -// return (int) (p - addr); -// } -// } -// } else { -// int p = abs_pos; -// int l = p - size - 1; -// for (; p > l; p--) { -// if (m.get(p) == b) { -// return p; -// } -// } -// } - return -1; - } - - @Override - public int limit() { - return memory.limit() - offset(); - } - - @Override - public ByteBuf limit(int limit) { - memory.limit(ix(limit)); + public ByteBuf reverseRead() { + abs_read_index = getNioBuffer().position(); return this; } - @Override - public ByteBuf markL() { - markLimit = memory.limit(); + public ByteBuf reverseWrite() { + abs_write_index = getNioBuffer().position(); return this; } - @Override - public ByteBuf markP() { - memory.mark(); - return this; - } - - @Override - public ByteBuffer nioBuffer() { - return memory; - } - - @Override - public int position() { - return memory.position() - offset(); - } - - @Override - public ByteBuf position(int position) { - memory.position(ix(position)); - return this; - } - - @Override - public void putByte(int index, byte b) { - memory.put(ix(index), b); - } - - @Override - protected void putByte0(byte b) { - memory.put(b); - } - - @Override - protected int putBytes0(byte[] src, int offset, int length) { - memory.put(src, offset, length); - return length; - } - - @Override - protected int putBytes00(ByteBuf src, int len) { - if (src.hasArray()) { - copy(src.array(), src.position(), address() + absPos(), len); - } else { - copy(src.address() + src.absPos(), address() + absPos(), len); - } - src.skip(len); - skip(len); - return len; + protected void setMemory(ByteBuffer memory) { + this.memory = memory; + super.setMemory(Unsafe.address(memory)); } @Override - protected int putBytes00(ByteBuffer src, int len) { - if (src.hasArray()) { - copy(src.array(), src.position(), address() + absPos(), len); - } else { - copy(Unsafe.address(src) + src.position(), address() + absPos(), len); + public ByteBuf duplicate() { + if (isReleased()) { + throw new IllegalStateException("released"); } - src.position(src.position() + len); - skip(len); - return len; - } - - @Override - public void putInt(int index, int value) { - memory.putInt(ix(index), value); - } - - @Override - public void putInt0(int value) { - memory.putInt(value); - } - - @Override - public void putIntLE(int index, int value) { - memory.putInt(ix(index), Integer.reverseBytes(value)); - } - - @Override - protected void putIntLE0(int value) { - memory.putInt(Integer.reverseBytes(value)); - } - - @Override - public void putLong(int index, long value) { - memory.putLong(ix(index), value); - } - - @Override - protected void putLong0(long value) { - memory.putLong(value); - } - - @Override - public void putLongLE(int index, long value) { - memory.putLong(ix(index), Long.reverseBytes(value)); - } - - @Override - protected void putLongLE0(long value) { - memory.putLong(Long.reverseBytes(value)); - } - - @Override - public void putShort(int index, int value) { - memory.putShort(ix(index), (short) value); - } - - @Override - protected void putShort0(int value) { - memory.putShort((short) value); - } - - @Override - public void putShortLE(int index, int value) { - memory.putShort(ix(index), Short.reverseBytes((short) value)); - } - - @Override - protected void putShortLE0(int value) { - memory.putShort(Short.reverseBytes((short) value)); - } - - @Override - public int remaining() { - return memory.remaining(); - } - - @Override - public ByteBuf resetL() { - memory.limit(markLimit); - return this; - } - - @Override - public ByteBuf resetP() { - memory.reset(); - return this; - } - - @Override - public ByteBuf reverse() { - return this; - } - - @Override - public ByteBuf skip(int length) { - memory.position(memory.position() + length); - return this; + this.retain(); + return new DuplicatedDirectByteBuf(this, 1); } } diff --git a/firenio-core/src/main/java/com/firenio/buffer/DuplicatedByteBuf.java b/firenio-core/src/main/java/com/firenio/buffer/DuplicatedByteBuf.java deleted file mode 100644 index 612e4f415..000000000 --- a/firenio-core/src/main/java/com/firenio/buffer/DuplicatedByteBuf.java +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright 2015 The FireNio Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.firenio.buffer; - -import java.nio.ByteBuffer; - -/** - * @author wangkai - */ -final class DuplicatedByteBuf extends ByteBuf { - - private ByteBuffer m; - private ByteBuf p; - - DuplicatedByteBuf(ByteBuffer memory, ByteBuf proto, int refCnt) { - this.p = proto; - this.m = memory; - this.referenceCount = refCnt; - } - - @Override - public byte absByte(int pos) { - return p.absByte(pos); - } - - @Override - public int absLimit() { - return p.absLimit(); - } - - @Override - public ByteBuf absLimit(int limit) { - throw unsupportedOperationException(); - } - - @Override - public int absPos() { - return p.absPos(); - } - - @Override - public ByteBuf absPos(int absPos) { - throw unsupportedOperationException(); - } - - @Override - public long address() { - return p.address(); - } - - @Override - public byte[] array() { - return p.array(); - } - - @Override - public int capacity() { - return p.capacity(); - } - - @Override - public ByteBuf clear() { - throw unsupportedOperationException(); - } - - @Override - public ByteBuf duplicate() { - return p.duplicate(); - } - - @Override - public void expansion(int cap) { - throw unsupportedOperationException(); - } - - @Override - public ByteBuf flip() { - m.limit(m.position()); - m.position(offset()); - return this; - } - - @Override - protected int get0(ByteBuffer dst, int len) { - throw unsupportedOperationException(); - } - - @Override - public byte getByte() { - throw unsupportedOperationException(); - } - - @Override - public byte getByte(int index) { - return p.getByte(index); - } - - @Override - public void getBytes(byte[] dst, int offset, int length) { - p.getBytes(dst, offset, length); - } - - @Override - public int getInt() { - throw unsupportedOperationException(); - } - - @Override - public int getInt(int index) { - return p.getInt(index); - } - - @Override - public int getIntLE() { - throw unsupportedOperationException(); - } - - @Override - public int getIntLE(int index) { - return p.getIntLE(index); - } - - @Override - public long getLong() { - throw unsupportedOperationException(); - } - - @Override - public long getLong(int index) { - return p.getLong(index); - } - - @Override - public long getLongLE() { - throw unsupportedOperationException(); - } - - @Override - public long getLongLE(int index) { - return p.getLongLE(index); - } - - @Override - public ByteBuffer getNioBuffer() { - return m; - } - - @Override - public short getShort() { - throw unsupportedOperationException(); - } - - @Override - public short getShort(int index) { - return p.getShort(index); - } - - @Override - public short getShortLE() { - throw unsupportedOperationException(); - } - - @Override - public short getShortLE(int index) { - return p.getShortLE(index); - } - - @Override - public short getUnsignedByte() { - throw unsupportedOperationException(); - } - - @Override - public short getUnsignedByte(int index) { - return p.getUnsignedByte(index); - } - - @Override - public long getUnsignedInt() { - throw unsupportedOperationException(); - } - - @Override - public long getUnsignedInt(int index) { - return p.getUnsignedInt(index); - } - - @Override - public long getUnsignedIntLE() { - throw unsupportedOperationException(); - } - - @Override - public long getUnsignedIntLE(int index) { - return p.getUnsignedIntLE(index); - } - - @Override - public int getUnsignedShort() { - throw unsupportedOperationException(); - } - - @Override - public int getUnsignedShort(int index) { - return p.getUnsignedShort(index); - } - - @Override - public int getUnsignedShortLE() { - throw unsupportedOperationException(); - } - - @Override - public int getUnsignedShortLE(int index) { - return p.getUnsignedShortLE(index); - } - - @Override - public boolean hasArray() { - return m.hasArray(); - } - - @Override - public boolean hasRemaining() { - return m.hasRemaining(); - } - - @Override - public int indexOf(byte b, int absPos, int size) { - return p.indexOf(b, absPos, size); - } - - @Override - public boolean isPooled() { - return p.isPooled(); - } - - @Override - public int lastIndexOf(byte b, int absPos, int size) { - return p.lastIndexOf(b, absPos, size); - } - - @Override - public int limit() { - return m.limit() - offset(); - } - - @Override - public ByteBuf limit(int limit) { - throw unsupportedOperationException(); - } - - @Override - public ByteBuf markL() { - throw unsupportedOperationException(); - } - - @Override - public ByteBuf markP() { - throw unsupportedOperationException(); - } - - @Override - public ByteBuffer nioBuffer() { - return m; - } - - @Override - public int position() { - return m.position() - offset(); - } - - @Override - public ByteBuf position(int position) { - throw unsupportedOperationException(); - } - - @Override - public void putByte(byte b) { - throw unsupportedOperationException(); - } - - @Override - public void putByte(int index, byte b) { - throw unsupportedOperationException(); - } - - @Override - protected void putByte0(byte b) { - throw unsupportedOperationException(); - } - - @Override - public void putBytes(byte[] src) { - throw unsupportedOperationException(); - } - - @Override - public int putBytes(byte[] src, int offset, int length) { - throw unsupportedOperationException(); - } - - @Override - public int putBytes(ByteBuf src) { - throw unsupportedOperationException(); - } - - @Override - public int putBytes(ByteBuf src, int length) { - throw unsupportedOperationException(); - } - - @Override - public int putBytes(ByteBuffer src) { - throw unsupportedOperationException(); - } - - @Override - public int putBytes(ByteBuffer src, int length) { - throw unsupportedOperationException(); - } - - @Override - protected int putBytes0(byte[] src, int offset, int length) { - throw unsupportedOperationException(); - } - - @Override - protected int putBytes00(ByteBuf src, int len) { - throw unsupportedOperationException(); - } - - @Override - protected int putBytes00(ByteBuffer src, int len) { - throw unsupportedOperationException(); - } - - @Override - public void putInt(int value) { - throw unsupportedOperationException(); - } - - @Override - public void putInt(int index, int value) { - throw unsupportedOperationException(); - } - - @Override - protected void putInt0(int value) { - throw unsupportedOperationException(); - } - - @Override - public void putIntLE(int value) { - throw unsupportedOperationException(); - } - - @Override - public void putIntLE(int index, int value) { - throw unsupportedOperationException(); - } - - @Override - protected void putIntLE0(int value) { - throw unsupportedOperationException(); - } - - @Override - public void putLong(int index, long value) { - throw unsupportedOperationException(); - } - - @Override - public float getFloat() { - throw unsupportedOperationException(); - } - - @Override - public float getFloat(int index) { - return p.getFloat(index); - } - - @Override - public float getFloatLE() { - throw unsupportedOperationException(); - } - - @Override - public float getFloatLE(int index) { - return p.getFloatLE(index); - } - - @Override - public double getDouble() { - throw unsupportedOperationException(); - } - - @Override - public double getDouble(int index) { - return p.getDouble(index); - } - - @Override - public double getDoubleLE() { - throw unsupportedOperationException(); - } - - @Override - public double getDoubleLE(int index) { - return p.getDoubleLE(index); - } - - @Override - public void putDouble(int index, double value) { - throw unsupportedOperationException(); - } - - @Override - public void putDoubleLE(int index, double value) { - throw unsupportedOperationException(); - } - - @Override - public void putFloat(int index, float value) { - throw unsupportedOperationException(); - } - - @Override - public void putFloatLE(int index, float value) { - throw unsupportedOperationException(); - } - - @Override - public void putLong(long value) { - throw unsupportedOperationException(); - } - - @Override - protected void putLong0(long value) { - throw unsupportedOperationException(); - } - - @Override - public void putLongLE(int index, long value) { - throw unsupportedOperationException(); - } - - @Override - public void putLongLE(long value) { - throw unsupportedOperationException(); - } - - @Override - protected void putLongLE0(long value) { - throw unsupportedOperationException(); - } - - @Override - public void putShort(int value) { - throw unsupportedOperationException(); - } - - @Override - public void putShort(int index, int value) { - throw unsupportedOperationException(); - } - - @Override - protected void putShort0(int value) { - throw unsupportedOperationException(); - } - - @Override - public void putShortLE(int value) { - throw unsupportedOperationException(); - } - - @Override - public void putShortLE(int index, int value) { - throw unsupportedOperationException(); - } - - @Override - protected void putShortLE0(int value) { - throw unsupportedOperationException(); - } - - @Override - protected void release0() { - p.release(); - } - - @Override - public int remaining() { - return m.remaining(); - } - - @Override - public ByteBuf resetL() { - throw unsupportedOperationException(); - } - - @Override - public ByteBuf resetP() { - throw unsupportedOperationException(); - } - - @Override - public ByteBuf reverse() { - return this; - } - - @Override - public ByteBuf skip(int length) { - m.position(m.position() + length); - return this; - } - - private UnsupportedOperationException unsupportedOperationException() { - return new UnsupportedOperationException(); - } - -} diff --git a/firenio-core/src/main/java/com/firenio/buffer/DuplicatedDirectByteBuf.java b/firenio-core/src/main/java/com/firenio/buffer/DuplicatedDirectByteBuf.java new file mode 100644 index 000000000..f470c8de6 --- /dev/null +++ b/firenio-core/src/main/java/com/firenio/buffer/DuplicatedDirectByteBuf.java @@ -0,0 +1,286 @@ +/* + * Copyright 2015 The FireNio Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.firenio.buffer; + +import java.nio.ByteBuffer; + +/** + * @author wangkai + */ +final class DuplicatedDirectByteBuf extends DirectByteBuf { + + private ByteBuf p; + + DuplicatedDirectByteBuf(ByteBuf proto, int refCnt) { + super(proto.getNioBuffer().duplicate()); + this.p = proto; + this.offset(proto.offset()); + this.absWriteIndex(proto.absWriteIndex()); + this.absReadIndex(proto.absReadIndex()); + this.referenceCount = refCnt; + } + + @Override + public byte getByteAbs(int pos) { + return p.getByteAbs(pos); + } + + @Override + public int capacity() { + return p.capacity(); + } + + @Override + public ByteBuf duplicate() { + return p.duplicate(); + } + + @Override + public void expansion(int cap) { + throw unsupportedOperationException(); + } + + @Override + public boolean isPooled() { + return p.isPooled(); + } + + @Override + public void writeByte(byte b) { + throw unsupportedOperationException(); + } + + @Override + public void setByte(int index, byte b) { + throw unsupportedOperationException(); + } + + @Override + protected void writeByte0(byte b) { + throw unsupportedOperationException(); + } + + @Override + public int setBytes(int index, ByteBuf src) { + throw unsupportedOperationException(); + } + + @Override + public int setBytes(int index, ByteBuffer src) { + throw unsupportedOperationException(); + } + + @Override + public int setBytes(int index, ByteBuf src, int length) { + throw unsupportedOperationException(); + } + + @Override + public int setBytes(int index, ByteBuffer src, int length) { + throw unsupportedOperationException(); + } + + @Override + public int setBytes(int index, byte[] src, int offset, int length) { + throw unsupportedOperationException(); + } + + @Override + public void setBytes(int index, byte[] src) { + throw unsupportedOperationException(); + } + + @Override + protected int setBytes0(int index, ByteBuf src, int len) { + throw unsupportedOperationException(); + } + + @Override + protected int setBytes0(int index, ByteBuffer src, int len) { + throw unsupportedOperationException(); + } + + @Override + protected int setBytes0(int index, byte[] src, int offset, int length) { + throw unsupportedOperationException(); + } + + @Override + public void writeBytes(byte[] src) { + throw unsupportedOperationException(); + } + + @Override + public int writeBytes(byte[] src, int offset, int length) { + throw unsupportedOperationException(); + } + + @Override + public int writeBytes(ByteBuf src) { + throw unsupportedOperationException(); + } + + @Override + public int writeBytes(ByteBuf src, int length) { + throw unsupportedOperationException(); + } + + @Override + public int writeBytes(ByteBuffer src) { + throw unsupportedOperationException(); + } + + @Override + public int writeBytes(ByteBuffer src, int length) { + throw unsupportedOperationException(); + } + + @Override + protected int writeBytes0(byte[] src, int offset, int length) { + throw unsupportedOperationException(); + } + + @Override + protected int writeBytes0(ByteBuf src, int len) { + throw unsupportedOperationException(); + } + + @Override + protected int writeBytes0(ByteBuffer src, int len) { + throw unsupportedOperationException(); + } + + @Override + public void writeInt(int value) { + throw unsupportedOperationException(); + } + + @Override + public void setInt(int index, int value) { + throw unsupportedOperationException(); + } + + @Override + protected void writeInt0(int value) { + throw unsupportedOperationException(); + } + + @Override + public void writeIntLE(int value) { + throw unsupportedOperationException(); + } + + @Override + public void setIntLE(int index, int value) { + throw unsupportedOperationException(); + } + + @Override + protected void writeIntLE0(int value) { + throw unsupportedOperationException(); + } + + @Override + public void setLong(int index, long value) { + throw unsupportedOperationException(); + } + + @Override + public void setDouble(int index, double value) { + throw unsupportedOperationException(); + } + + @Override + public void setDoubleLE(int index, double value) { + throw unsupportedOperationException(); + } + + @Override + public void setFloat(int index, float value) { + throw unsupportedOperationException(); + } + + @Override + public void setFloatLE(int index, float value) { + throw unsupportedOperationException(); + } + + @Override + public void writeLong(long value) { + throw unsupportedOperationException(); + } + + @Override + protected void writeLong0(long value) { + throw unsupportedOperationException(); + } + + @Override + public void setLongLE(int index, long value) { + throw unsupportedOperationException(); + } + + @Override + public void writeLongLE(long value) { + throw unsupportedOperationException(); + } + + @Override + protected void writeLongLE0(long value) { + throw unsupportedOperationException(); + } + + @Override + public void writeShort(int value) { + throw unsupportedOperationException(); + } + + @Override + public void setShort(int index, int value) { + throw unsupportedOperationException(); + } + + @Override + protected void writeShort0(int value) { + throw unsupportedOperationException(); + } + + @Override + public void writeShortLE(int value) { + throw unsupportedOperationException(); + } + + @Override + public void setShortLE(int index, int value) { + throw unsupportedOperationException(); + } + + @Override + protected void writeShortLE0(int value) { + throw unsupportedOperationException(); + } + + @Override + public ByteBuf reverseWrite() { + throw unsupportedOperationException(); + } + + @Override + protected void release0() { + p.release(); + } + +} diff --git a/firenio-core/src/main/java/com/firenio/buffer/DuplicatedHeapByteBuf.java b/firenio-core/src/main/java/com/firenio/buffer/DuplicatedHeapByteBuf.java new file mode 100644 index 000000000..df0288e02 --- /dev/null +++ b/firenio-core/src/main/java/com/firenio/buffer/DuplicatedHeapByteBuf.java @@ -0,0 +1,286 @@ +/* + * Copyright 2015 The FireNio Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.firenio.buffer; + +import java.nio.ByteBuffer; + +/** + * @author wangkai + */ +final class DuplicatedHeapByteBuf extends HeapByteBuf { + + private ByteBuf p; + + DuplicatedHeapByteBuf(ByteBuf proto, int refCnt) { + super(proto.getNioBuffer()); + this.p = proto; + this.offset(proto.offset()); + this.absWriteIndex(proto.absWriteIndex()); + this.absReadIndex(proto.absReadIndex()); + this.referenceCount = refCnt; + } + + @Override + public byte getByteAbs(int pos) { + return p.getByteAbs(pos); + } + + @Override + public int capacity() { + return p.capacity(); + } + + @Override + public ByteBuf duplicate() { + return p.duplicate(); + } + + @Override + public void expansion(int cap) { + throw unsupportedOperationException(); + } + + @Override + public boolean isPooled() { + return p.isPooled(); + } + + @Override + public void writeByte(byte b) { + throw unsupportedOperationException(); + } + + @Override + public void setByte(int index, byte b) { + throw unsupportedOperationException(); + } + + @Override + protected void writeByte0(byte b) { + throw unsupportedOperationException(); + } + + @Override + public int setBytes(int index, ByteBuf src) { + throw unsupportedOperationException(); + } + + @Override + public int setBytes(int index, ByteBuffer src) { + throw unsupportedOperationException(); + } + + @Override + public int setBytes(int index, ByteBuf src, int length) { + throw unsupportedOperationException(); + } + + @Override + public int setBytes(int index, ByteBuffer src, int length) { + throw unsupportedOperationException(); + } + + @Override + public int setBytes(int index, byte[] src, int offset, int length) { + throw unsupportedOperationException(); + } + + @Override + public void setBytes(int index, byte[] src) { + throw unsupportedOperationException(); + } + + @Override + protected int setBytes0(int index, ByteBuf src, int len) { + throw unsupportedOperationException(); + } + + @Override + protected int setBytes0(int index, ByteBuffer src, int len) { + throw unsupportedOperationException(); + } + + @Override + protected int setBytes0(int index, byte[] src, int offset, int length) { + throw unsupportedOperationException(); + } + + @Override + public void writeBytes(byte[] src) { + throw unsupportedOperationException(); + } + + @Override + public int writeBytes(byte[] src, int offset, int length) { + throw unsupportedOperationException(); + } + + @Override + public int writeBytes(ByteBuf src) { + throw unsupportedOperationException(); + } + + @Override + public int writeBytes(ByteBuf src, int length) { + throw unsupportedOperationException(); + } + + @Override + public int writeBytes(ByteBuffer src) { + throw unsupportedOperationException(); + } + + @Override + public int writeBytes(ByteBuffer src, int length) { + throw unsupportedOperationException(); + } + + @Override + protected int writeBytes0(byte[] src, int offset, int length) { + throw unsupportedOperationException(); + } + + @Override + protected int writeBytes0(ByteBuf src, int len) { + throw unsupportedOperationException(); + } + + @Override + protected int writeBytes0(ByteBuffer src, int len) { + throw unsupportedOperationException(); + } + + @Override + public void writeInt(int value) { + throw unsupportedOperationException(); + } + + @Override + public void setInt(int index, int value) { + throw unsupportedOperationException(); + } + + @Override + protected void writeInt0(int value) { + throw unsupportedOperationException(); + } + + @Override + public void writeIntLE(int value) { + throw unsupportedOperationException(); + } + + @Override + public void setIntLE(int index, int value) { + throw unsupportedOperationException(); + } + + @Override + protected void writeIntLE0(int value) { + throw unsupportedOperationException(); + } + + @Override + public void setLong(int index, long value) { + throw unsupportedOperationException(); + } + + @Override + public void setDouble(int index, double value) { + throw unsupportedOperationException(); + } + + @Override + public void setDoubleLE(int index, double value) { + throw unsupportedOperationException(); + } + + @Override + public void setFloat(int index, float value) { + throw unsupportedOperationException(); + } + + @Override + public void setFloatLE(int index, float value) { + throw unsupportedOperationException(); + } + + @Override + public void writeLong(long value) { + throw unsupportedOperationException(); + } + + @Override + protected void writeLong0(long value) { + throw unsupportedOperationException(); + } + + @Override + public void setLongLE(int index, long value) { + throw unsupportedOperationException(); + } + + @Override + public void writeLongLE(long value) { + throw unsupportedOperationException(); + } + + @Override + protected void writeLongLE0(long value) { + throw unsupportedOperationException(); + } + + @Override + public void writeShort(int value) { + throw unsupportedOperationException(); + } + + @Override + public void setShort(int index, int value) { + throw unsupportedOperationException(); + } + + @Override + protected void writeShort0(int value) { + throw unsupportedOperationException(); + } + + @Override + public void writeShortLE(int value) { + throw unsupportedOperationException(); + } + + @Override + public void setShortLE(int index, int value) { + throw unsupportedOperationException(); + } + + @Override + protected void writeShortLE0(int value) { + throw unsupportedOperationException(); + } + + @Override + public ByteBuf reverseWrite() { + throw unsupportedOperationException(); + } + + @Override + protected void release0() { + p.release(); + } + +} diff --git a/firenio-core/src/main/java/com/firenio/buffer/DuplicatedUnsafeByteBuf.java b/firenio-core/src/main/java/com/firenio/buffer/DuplicatedUnsafeByteBuf.java index c03adbe6f..e0864d734 100644 --- a/firenio-core/src/main/java/com/firenio/buffer/DuplicatedUnsafeByteBuf.java +++ b/firenio-core/src/main/java/com/firenio/buffer/DuplicatedUnsafeByteBuf.java @@ -29,43 +29,13 @@ final class DuplicatedUnsafeByteBuf extends UnsafeByteBuf { this.p = proto; this.referenceCount = refCnt; this.capacity(proto.capacity()); - this.absLimit(proto.absLimit()); - this.absPos(proto.absPos()); + this.absWriteIndex(proto.absWriteIndex()); + this.absReadIndex(proto.absReadIndex()); } @Override - public byte absByte(int pos) { - return p.absByte(pos); - } - - @Override - public int absLimit() { - return p.absLimit(); - } - - @Override - public ByteBuf absLimit(int limit) { - throw unsupportedOperationException(); - } - - @Override - public int absPos() { - return p.absPos(); - } - - @Override - public ByteBuf absPos(int absPos) { - throw unsupportedOperationException(); - } - - @Override - public long address() { - return p.address(); - } - - @Override - public byte[] array() { - return p.array(); + public byte getByteAbs(int pos) { + return p.getByteAbs(pos); } @Override @@ -73,11 +43,6 @@ public int capacity() { return p.capacity(); } - @Override - public ByteBuf clear() { - throw unsupportedOperationException(); - } - @Override public ByteBuf duplicate() { return p.duplicate(); @@ -89,382 +54,227 @@ public void expansion(int cap) { } @Override - protected int get0(ByteBuffer dst, int len) { - throw unsupportedOperationException(); - } - - @Override - public byte getByte() { - throw unsupportedOperationException(); - } - - @Override - public byte getByte(int index) { - return p.getByte(index); - } - - @Override - public void getBytes(byte[] dst, int offset, int length) { - p.getBytes(dst, offset, length); - } - - @Override - public int getInt() { - throw unsupportedOperationException(); - } - - @Override - public int getInt(int index) { - return p.getInt(index); - } - - @Override - public int getIntLE() { - throw unsupportedOperationException(); - } - - @Override - public int getIntLE(int index) { - return p.getIntLE(index); - } - - @Override - public long getLong() { - throw unsupportedOperationException(); - } - - @Override - public long getLong(int index) { - return p.getLong(index); - } - - @Override - public long getLongLE() { - throw unsupportedOperationException(); - } - - @Override - public long getLongLE(int index) { - return p.getLongLE(index); - } - - @Override - public short getShort() { - throw unsupportedOperationException(); - } - - @Override - public short getShort(int index) { - return p.getShort(index); - } - - @Override - public short getShortLE() { - throw unsupportedOperationException(); - } - - @Override - public short getShortLE(int index) { - return p.getShortLE(index); - } - - @Override - public short getUnsignedByte() { - throw unsupportedOperationException(); - } - - @Override - public short getUnsignedByte(int index) { - return p.getUnsignedByte(index); - } - - @Override - public long getUnsignedInt() { - throw unsupportedOperationException(); - } - - @Override - public long getUnsignedInt(int index) { - return p.getUnsignedInt(index); - } - - @Override - public long getUnsignedIntLE() { - throw unsupportedOperationException(); - } - - @Override - public long getUnsignedIntLE(int index) { - return p.getUnsignedIntLE(index); + public boolean isPooled() { + return p.isPooled(); } @Override - public int getUnsignedShort() { + public void writeByte(byte b) { throw unsupportedOperationException(); } @Override - public int getUnsignedShort(int index) { - return p.getUnsignedShort(index); - } - - @Override - public float getFloat() { + public void setByte(int index, byte b) { throw unsupportedOperationException(); } @Override - public float getFloat(int index) { - return p.getFloat(index); - } - - @Override - public float getFloatLE() { + protected void writeByte0(byte b) { throw unsupportedOperationException(); } @Override - public float getFloatLE(int index) { - return p.getFloatLE(index); - } - - @Override - public double getDouble() { + public int setBytes(int index, ByteBuf src) { throw unsupportedOperationException(); } @Override - public double getDouble(int index) { - return p.getDouble(index); - } - - @Override - public double getDoubleLE() { + public int setBytes(int index, ByteBuffer src) { throw unsupportedOperationException(); } @Override - public double getDoubleLE(int index) { - return p.getDoubleLE(index); - } - - @Override - public void putDouble(int index, double value) { + public int setBytes(int index, ByteBuf src, int length) { throw unsupportedOperationException(); } @Override - public void putDoubleLE(int index, double value) { + public int setBytes(int index, ByteBuffer src, int length) { throw unsupportedOperationException(); } @Override - public void putFloat(int index, float value) { + public int setBytes(int index, byte[] src, int offset, int length) { throw unsupportedOperationException(); } @Override - public void putFloatLE(int index, float value) { + public void setBytes(int index, byte[] src) { throw unsupportedOperationException(); } @Override - public int getUnsignedShortLE() { + protected int setBytes0(int index, ByteBuf src, int len) { throw unsupportedOperationException(); } @Override - public int getUnsignedShortLE(int index) { - return p.getUnsignedShortLE(index); - } - - @Override - public boolean hasArray() { - return p.hasArray(); - } - - @Override - public int indexOf(byte b, int absPos, int size) { - return p.indexOf(b, absPos, size); - } - - @Override - public boolean isPooled() { - return p.isPooled(); - } - - @Override - public int lastIndexOf(byte b, int absPos, int size) { - return p.lastIndexOf(b, absPos, size); - } - - @Override - public ByteBuf limit(int limit) { + protected int setBytes0(int index, ByteBuffer src, int len) { throw unsupportedOperationException(); } @Override - public ByteBuf markL() { + protected int setBytes0(int index, byte[] src, int offset, int length) { throw unsupportedOperationException(); } @Override - public ByteBuf markP() { + public void writeBytes(byte[] src) { throw unsupportedOperationException(); } @Override - public ByteBuf position(int position) { + public int writeBytes(byte[] src, int offset, int length) { throw unsupportedOperationException(); } @Override - public void putByte(byte b) { + public int writeBytes(ByteBuf src) { throw unsupportedOperationException(); } @Override - public void putByte(int index, byte b) { + public int writeBytes(ByteBuf src, int length) { throw unsupportedOperationException(); } @Override - protected void putByte0(byte b) { + public int writeBytes(ByteBuffer src) { throw unsupportedOperationException(); } @Override - public void putBytes(byte[] src) { + public int writeBytes(ByteBuffer src, int length) { throw unsupportedOperationException(); } @Override - public int putBytes(byte[] src, int offset, int length) { + protected int writeBytes0(byte[] src, int offset, int length) { throw unsupportedOperationException(); } @Override - public int putBytes(ByteBuf src) { + protected int writeBytes0(ByteBuf src, int len) { throw unsupportedOperationException(); } @Override - public int putBytes(ByteBuf src, int length) { + protected int writeBytes0(ByteBuffer src, int len) { throw unsupportedOperationException(); } @Override - public int putBytes(ByteBuffer src) { + public void writeInt(int value) { throw unsupportedOperationException(); } @Override - public int putBytes(ByteBuffer src, int length) { + public void setInt(int index, int value) { throw unsupportedOperationException(); } @Override - protected int putBytes0(byte[] src, int offset, int length) { + protected void writeInt0(int value) { throw unsupportedOperationException(); } @Override - protected int putBytes00(ByteBuf src, int len) { + public void writeIntLE(int value) { throw unsupportedOperationException(); } @Override - protected int putBytes00(ByteBuffer src, int len) { + public void setIntLE(int index, int value) { throw unsupportedOperationException(); } @Override - public void putInt(int value) { + protected void writeIntLE0(int value) { throw unsupportedOperationException(); } @Override - public void putInt(int index, int value) { + public void setLong(int index, long value) { throw unsupportedOperationException(); } @Override - protected void putInt0(int value) { + public void setDouble(int index, double value) { throw unsupportedOperationException(); } @Override - public void putIntLE(int value) { + public void setDoubleLE(int index, double value) { throw unsupportedOperationException(); } @Override - public void putIntLE(int index, int value) { + public void setFloat(int index, float value) { throw unsupportedOperationException(); } @Override - protected void putIntLE0(int value) { + public void setFloatLE(int index, float value) { throw unsupportedOperationException(); } @Override - public void putLong(int index, long value) { + public void writeLong(long value) { throw unsupportedOperationException(); } @Override - public void putLong(long value) { + protected void writeLong0(long value) { throw unsupportedOperationException(); } @Override - protected void putLong0(long value) { + public void setLongLE(int index, long value) { throw unsupportedOperationException(); } @Override - public void putLongLE(int index, long value) { + public void writeLongLE(long value) { throw unsupportedOperationException(); } @Override - public void putLongLE(long value) { + protected void writeLongLE0(long value) { throw unsupportedOperationException(); } @Override - protected void putLongLE0(long value) { + public void writeShort(int value) { throw unsupportedOperationException(); } @Override - public void putShort(int value) { + public void setShort(int index, int value) { throw unsupportedOperationException(); } @Override - public void putShort(int index, int value) { + protected void writeShort0(int value) { throw unsupportedOperationException(); } @Override - protected void putShort0(int value) { + public void writeShortLE(int value) { throw unsupportedOperationException(); } @Override - public void putShortLE(int value) { + public void setShortLE(int index, int value) { throw unsupportedOperationException(); } @Override - public void putShortLE(int index, int value) { + protected void writeShortLE0(int value) { throw unsupportedOperationException(); } @Override - protected void putShortLE0(int value) { + public ByteBuf reverseWrite() { throw unsupportedOperationException(); } @@ -473,23 +283,4 @@ protected void release0() { p.release(); } - @Override - public ByteBuf resetL() { - throw unsupportedOperationException(); - } - - @Override - public ByteBuf resetP() { - throw unsupportedOperationException(); - } - - @Override - public ByteBuf reverse() { - return this; - } - - private UnsupportedOperationException unsupportedOperationException() { - return new UnsupportedOperationException(); - } - } diff --git a/firenio-core/src/main/java/com/firenio/buffer/HeapByteBuf.java b/firenio-core/src/main/java/com/firenio/buffer/HeapByteBuf.java index 9cc764cfc..beb3d3be3 100644 --- a/firenio-core/src/main/java/com/firenio/buffer/HeapByteBuf.java +++ b/firenio-core/src/main/java/com/firenio/buffer/HeapByteBuf.java @@ -22,12 +22,8 @@ abstract class HeapByteBuf extends ByteBuf { - protected int limit; - protected int markLimit; - protected int markPos; protected byte[] memory; protected ByteBuffer nioBuffer; - protected int pos; HeapByteBuf(byte[] memory) { this.memory = memory; @@ -39,83 +35,117 @@ abstract class HeapByteBuf extends ByteBuf { } @Override - public byte absByte(int pos) { - return memory[pos]; + public byte[] array() { + return memory; } @Override - public int absLimit() { - return limit; + public long address() { + return -1; } @Override - public ByteBuf absLimit(int limit) { - this.limit = limit; - return this; + public void compact() { + if (!hasReadableBytes()) { + clear(); + return; + } + int remain = readableBytes(); + int abs_read_index = absReadIndex(); + int abs_write_index = absWriteIndex(); + int src_offset = abs_read_index; + int dst_offset = offset(); + System.arraycopy(memory, src_offset, memory, dst_offset, remain); + readIndex(0); + writeIndex(remain); } @Override - public int absPos() { - return pos; + public ByteBuf duplicate() { + if (isReleased()) { + throw new IllegalStateException("released"); + } + this.retain(); + return new DuplicatedHeapByteBuf(this, 1); } @Override - public ByteBuf absPos(int pos) { - this.pos = pos; - return this; + public byte getByteAbs(int pos) { + return memory[pos]; } + @Override - public byte[] array() { - return memory; + public void getBytes(int index, byte[] dst, int offset, int length) { + System.arraycopy(memory, ix(index), dst, offset, length); } @Override - public ByteBuf clear() { - this.pos = offset(); - this.limit = ix(capacity()); - return this; + protected int getBytes0(int index, ByteBuf dst, int len) { + if (dst.hasArray()) { + copy(memory, ix(index), dst.array(), dst.writeIndex(), len); + } else { + copy(memory, ix(index), dst.address() + dst.absWriteIndex(), len); + } + dst.skipWrite(len); + return len; } @Override - public ByteBuf flip() { - this.limit = pos; - this.pos = offset(); - return this; + protected int getBytes0(int index, ByteBuffer dst, int len) { + if (dst.hasArray()) { + copy(memory, ix(index), dst.array(), dst.position(), len); + } else { + copy(memory, ix(index), Unsafe.address(dst) + dst.position(), len); + } + dst.position(dst.position() + len); + return len; + } + + @Override + public void readBytes(byte[] dst, int offset, int length) { + System.arraycopy(memory, absReadIndex(), dst, offset, length); + skipRead(length); } @Override - protected int get0(ByteBuffer dst, int len) { + protected int readBytes0(ByteBuf dst, int len) { if (dst.hasArray()) { - copy(memory, absPos(), dst.array(), dst.position(), len); + copy(memory, absReadIndex(), dst.array(), dst.writeIndex(), len); } else { - copy(memory, absPos(), Unsafe.address(dst) + dst.position(), len); + copy(memory, absReadIndex(), dst.address() + dst.absWriteIndex(), len); } - dst.position(dst.position() + len); - skip(len); + dst.skipWrite(len); + skipRead(len); return len; } @Override - public byte getByte() { - return memory[pos++]; + protected int readBytes0(ByteBuffer dst, int len) { + if (dst.hasArray()) { + copy(memory, absReadIndex(), dst.array(), dst.position(), len); + } else { + copy(memory, absReadIndex(), Unsafe.address(dst) + dst.position(), len); + } + dst.position(dst.position() + len); + skipRead(len); + return len; } @Override - public byte getByte(int index) { - return memory[ix(index)]; + public byte readByte() { + return memory[abs_read_index++]; } @Override - public void getBytes(byte[] dst, int offset, int length) { - System.arraycopy(memory, pos, dst, offset, length); - this.pos += length; + public byte getByte(int index) { + return memory[ix(index)]; } @Override - public int getInt() { - int v = ByteUtil.getInt(memory, pos); - this.pos += 4; + public int readInt() { + int v = ByteUtil.getInt(memory, absReadIndex()); + skipRead(4); return v; } @@ -125,9 +155,9 @@ public int getInt(int index) { } @Override - public int getIntLE() { - int v = ByteUtil.getIntLE(memory, pos); - this.pos += 4; + public int readIntLE() { + int v = ByteUtil.getIntLE(memory, absReadIndex()); + skipRead(4); return v; } @@ -137,9 +167,9 @@ public int getIntLE(int offset) { } @Override - public long getLong() { - long v = ByteUtil.getLong(memory, pos); - this.pos += 8; + public long readLong() { + long v = ByteUtil.getLong(memory, absReadIndex()); + skipRead(8); return v; } @@ -149,9 +179,9 @@ public long getLong(int index) { } @Override - public long getLongLE() { - long v = ByteUtil.getLongLE(memory, pos); - this.pos += 8; + public long readLongLE() { + long v = ByteUtil.getLongLE(memory, absReadIndex()); + skipRead(8); return v; } @@ -169,9 +199,9 @@ public ByteBuffer getNioBuffer() { } @Override - public short getShort() { - short v = ByteUtil.getShort(memory, pos); - this.pos += 2; + public short readShort() { + short v = ByteUtil.getShort(memory, absReadIndex()); + skipRead(2); return v; } @@ -181,9 +211,9 @@ public short getShort(int index) { } @Override - public short getShortLE() { - short v = ByteUtil.getShortLE(memory, pos); - this.pos += 2; + public short readShortLE() { + short v = ByteUtil.getShortLE(memory, absReadIndex()); + skipRead(2); return v; } @@ -193,8 +223,8 @@ public short getShortLE(int index) { } @Override - public short getUnsignedByte() { - return (short) (getByte() & 0xff); + public short readUnsignedByte() { + return (short) (readByte() & 0xff); } @Override @@ -203,33 +233,33 @@ public short getUnsignedByte(int index) { } @Override - public long getUnsignedInt() { - long v = ByteUtil.getInt(memory, pos) & 0xffffffffL; - this.pos += 4; + public long readUnsignedInt() { + long v = toUnsignedInt(ByteUtil.getInt(memory, absReadIndex())); + skipRead(4); return v; } @Override public long getUnsignedInt(int index) { - return ByteUtil.getInt(memory, ix(index)) & 0xffffffffL; + return toUnsignedInt(ByteUtil.getInt(memory, ix(index))); } @Override - public long getUnsignedIntLE() { - long v = ByteUtil.getIntLE(memory, pos) & 0xffffffffL; - this.pos += 4; + public long readUnsignedIntLE() { + long v = toUnsignedInt(ByteUtil.getIntLE(memory, absReadIndex())); + skipRead(4); return v; } @Override public long getUnsignedIntLE(int index) { - return ByteUtil.getIntLE(memory, ix(index)) & 0xffffffffL; + return toUnsignedInt(ByteUtil.getIntLE(memory, ix(index))); } @Override - public int getUnsignedShort() { - int v = ByteUtil.getShort(memory, pos) & 0xffff; - this.pos += 2; + public int readUnsignedShort() { + int v = ByteUtil.getShort(memory, absReadIndex()) & 0xffff; + skipRead(2); return v; } @@ -239,9 +269,9 @@ public int getUnsignedShort(int index) { } @Override - public int getUnsignedShortLE() { - int v = ByteUtil.getShortLE(memory, pos) & 0xffff; - this.pos += 2; + public int readUnsignedShortLE() { + int v = ByteUtil.getShortLE(memory, absReadIndex()) & 0xffff; + skipRead(2); return v; } @@ -255,11 +285,6 @@ public boolean hasArray() { return true; } - @Override - public boolean hasRemaining() { - return pos < limit; - } - @Override public int indexOf(byte b, int abs_pos, int size) { int p = abs_pos; @@ -287,178 +312,147 @@ public int lastIndexOf(byte b, int abs_pos, int size) { } @Override - public int limit() { - return limit - offset(); - } - - @Override - public ByteBuf limit(int limit) { - this.limit = ix(limit); - return this; - } - - @Override - public ByteBuf markL() { - markLimit = limit; - return this; - } - - @Override - public ByteBuf markP() { - markPos = pos; - return this; - } - - @Override - public ByteBuffer nioBuffer() { - ByteBuffer buffer = getNioBuffer(); - return (ByteBuffer) buffer.limit(limit).position(pos); + public void setByte(int index, byte b) { + memory[ix(index)] = b; } @Override - public int position() { - return pos - offset(); + protected void writeByte0(byte b) { + memory[abs_write_index++] = b; } @Override - public ByteBuf position(int position) { - this.pos = ix(position); - return this; + protected int setBytes0(int index, byte[] src, int offset, int length) { + System.arraycopy(src, offset, memory, ix(index), length); + return length; } @Override - public void putByte(int index, byte b) { - memory[ix(index)] = b; + protected int setBytes0(int index, ByteBuf src, int len) { + if (src.hasArray()) { + copy(src.array(), src.absReadIndex(), memory, ix(index), len); + } else { + copy(src.address() + src.absReadIndex(), memory, ix(index), len); + } + src.skipRead(len); + return len; } @Override - protected void putByte0(byte b) { - memory[pos++] = b; + protected int setBytes0(int index, ByteBuffer src, int len) { + if (src.hasArray()) { + copy(src.array(), src.position(), memory, ix(index), len); + } else { + copy(Unsafe.address(src) + src.position(), memory, ix(index), len); + } + src.position(src.position() + len); + return len; } @Override - protected int putBytes0(byte[] src, int offset, int length) { - System.arraycopy(src, offset, memory, pos, length); - this.pos += length; + protected int writeBytes0(byte[] src, int offset, int length) { + System.arraycopy(src, offset, memory, absWriteIndex(), length); + skipWrite(length); return length; } @Override - protected int putBytes00(ByteBuf src, int len) { + protected int writeBytes0(ByteBuf src, int len) { if (src.hasArray()) { - copy(src.array(), src.absPos(), memory, absPos(), len); + copy(src.array(), src.absReadIndex(), memory, absWriteIndex(), len); } else { - copy(src.address() + src.absPos(), memory, absPos(), len); + copy(src.address() + src.absReadIndex(), memory, absWriteIndex(), len); } - src.skip(len); - skip(len); + src.skipRead(len); + skipWrite(len); return len; } @Override - protected int putBytes00(ByteBuffer src, int len) { + protected int writeBytes0(ByteBuffer src, int len) { if (src.hasArray()) { - copy(src.array(), src.position(), memory, absPos(), len); + copy(src.array(), src.position(), memory, absWriteIndex(), len); } else { - copy(Unsafe.address(src) + src.position(), memory, absPos(), len); + copy(Unsafe.address(src) + src.position(), memory, absWriteIndex(), len); } src.position(src.position() + len); - skip(len); + skipWrite(len); return len; } @Override - public void putInt(int index, int value) { + public void setInt(int index, int value) { ByteUtil.putInt(memory, value, ix(index)); } @Override - protected void putInt0(int value) { - ByteUtil.putInt(memory, value, pos); - pos += 4; + protected void writeInt0(int value) { + ByteUtil.putInt(memory, value, absWriteIndex()); + skipWrite(4); } @Override - public void putIntLE(int index, int value) { + public void setIntLE(int index, int value) { ByteUtil.putIntLE(memory, value, ix(index)); } @Override - protected void putIntLE0(int value) { - ByteUtil.putIntLE(memory, value, pos); - pos += 4; + protected void writeIntLE0(int value) { + ByteUtil.putIntLE(memory, value, absWriteIndex()); + skipWrite(4); } @Override - public void putLong(int index, long value) { + public void setLong(int index, long value) { ByteUtil.putLong(memory, value, ix(index)); } @Override - protected void putLong0(long value) { - ByteUtil.putLong(memory, value, pos); - pos += 8; + protected void writeLong0(long value) { + ByteUtil.putLong(memory, value, absWriteIndex()); + skipWrite(8); } @Override - public void putLongLE(int index, long value) { + public void setLongLE(int index, long value) { ByteUtil.putLongLE(memory, value, ix(index)); } @Override - protected void putLongLE0(long value) { - ByteUtil.putLongLE(memory, value, pos); - pos += 8; + protected void writeLongLE0(long value) { + ByteUtil.putLongLE(memory, value, absWriteIndex()); + skipWrite(8); } @Override - public void putShort(int index, int value) { + public void setShort(int index, int value) { ByteUtil.putShort(memory, (short) value, ix(index)); } @Override - protected void putShort0(int value) { - ByteUtil.putShort(memory, (short) value, pos); - pos += 2; + protected void writeShort0(int value) { + ByteUtil.putShort(memory, (short) value, absWriteIndex()); + skipWrite(2); } @Override - public void putShortLE(int index, int value) { + public void setShortLE(int index, int value) { ByteUtil.putShortLE(memory, (short) value, ix(index)); } @Override - protected void putShortLE0(int value) { - ByteUtil.putShortLE(memory, (short) value, pos); - pos += 2; - } - - @Override - public int remaining() { - return limit - pos; + protected void writeShortLE0(int value) { + ByteUtil.putShortLE(memory, (short) value, absWriteIndex()); + skipWrite(2); } - @Override - public ByteBuf resetL() { - limit = markLimit; - return this; - } - - @Override - public ByteBuf resetP() { - pos = markPos; + public ByteBuf reverseRead() { + abs_read_index = getNioBuffer().position(); return this; } - @Override - public ByteBuf reverse() { - pos = nioBuffer.position(); - return this; - } - - @Override - public ByteBuf skip(int length) { - pos += length; + public ByteBuf reverseWrite() { + abs_write_index = getNioBuffer().position(); return this; } diff --git a/firenio-core/src/main/java/com/firenio/buffer/PooledByteBufAllocator.java b/firenio-core/src/main/java/com/firenio/buffer/PooledByteBufAllocator.java index fbe584f93..ae7eb691c 100644 --- a/firenio-core/src/main/java/com/firenio/buffer/PooledByteBufAllocator.java +++ b/firenio-core/src/main/java/com/firenio/buffer/PooledByteBufAllocator.java @@ -17,15 +17,13 @@ import java.nio.ByteBuffer; import java.util.Arrays; -import java.util.BitSet; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; import com.firenio.Develop; import com.firenio.Options; -import com.firenio.collection.LinkedBQStack; -import com.firenio.collection.Stack; +import com.firenio.collection.ObjectPool; import com.firenio.common.DateUtil; import com.firenio.common.Unsafe; import com.firenio.common.Util; @@ -35,43 +33,38 @@ */ public final class PooledByteBufAllocator extends ByteBufAllocator { - public static final Map BUF_DEBUGS; - public static final ByteBufException EXPANSION_FAILED = EXPANSION_FAILED(); - static final int BYTEBUF_BUFFER = 1024 * 8; - static final boolean BYTEBUF_RECYCLE = Options.isBufRecycle(); - static final boolean ENABLE_UNSAFE_BUF = Options.isEnableUnsafeBuf(); + public static final Map BUF_DEBUGS = NEW_BUF_DEBUGS(); + public static final ByteBufException EXPANSION_FAILED = EXPANSION_FAILED(); + static final int ADDRESS_BITS_PER_WORD = 6; + static final int BUF_POOL_SIZE = 1024 * 8; + static final boolean BUF_POOL_ENABLE = Options.isBufRecycle(); + static final ThreadLocal> BUF_POOL = new ThreadLocal>() { - static { - if (Develop.BUF_DEBUG) { - BUF_DEBUGS = new ConcurrentHashMap<>(); - } else { - BUF_DEBUGS = null; + @Override + protected ObjectPool initialValue() { + return new ObjectPool<>(Thread.currentThread(), BUF_POOL_SIZE); } - } - - private final int[] blockEnds; - private final Stack bufBuffer; - private final int capacity; - private final BitSet frees; - private final boolean isDirect; - private final ReentrantLock lock = new ReentrantLock(); - private final int unit; - private long address = -1; - private ByteBuffer directMemory; - private byte[] heapMemory; - private int mark; + }; + + private final int[] blockEnds; + private final int capacity; + private final long[] frees; + private final boolean isDirect; + private final int unit; + private final ByteBufAllocator unpooled; + private final ReentrantLock lock = new ReentrantLock(); + private long address = -1; + private ByteBuffer directMemory; + private byte[] heapMemory; + private int mark; public PooledByteBufAllocator(ByteBufAllocatorGroup group) { this.unit = group.getUnit(); this.isDirect = group.isDirect(); this.capacity = group.getCapacity(); - this.frees = new BitSet(getCapacity()); + this.frees = new long[getCapacity() / 8]; this.blockEnds = new int[getCapacity()]; - if (BYTEBUF_RECYCLE) { - bufBuffer = new LinkedBQStack<>(BYTEBUF_BUFFER); - } else { - bufBuffer = null; - } + this.unpooled = UnpooledByteBufAllocator.get(); } static ByteBufException EXPANSION_FAILED() { @@ -86,7 +79,7 @@ public ByteBuf allocate() { @Override public ByteBuf allocate(int limit) { if (limit < 1) { - return null; + return ByteBuf.empty(); } int size = (limit + unit - 1) / unit; int blockStart; @@ -94,7 +87,7 @@ public ByteBuf allocate(int limit) { lock.lock(); try { if (!isRunning()) { - return null; + return unpooled.allocate(limit); } int mark = this.mark; blockStart = allocate(mark, capacity, size); @@ -107,9 +100,9 @@ public ByteBuf allocate(int limit) { ByteBuf buf; if (blockStart == -1) { // FIXME 是否申请java内存 - return ByteBuf.heap(limit); + return unpooled.allocate(limit); } else { - buf = newByteBuf().produce(blockStart, blockEnds[blockStart]); + buf = newByteBuf().produce(blockStart, size); if (Develop.BUF_DEBUG) { BufDebug d = new BufDebug(); d.buf = buf; @@ -122,35 +115,38 @@ public ByteBuf allocate(int limit) { // FIXME 判断余下的是否足够,否则退出循环 private int allocate(int start, int end, int size) { - int freeSize = 0; - int[] blockEnds = this.blockEnds; - BitSet frees = this.frees; - for (; start < end; ) { - int pos = start; - if (!frees.get(pos)) { - start = blockEnds[pos]; - freeSize = 0; + int[] blockEnds = this.blockEnds; + int pos = start; + int limit = pos + size; + if (limit >= end) { + return -1; + } + for (; ; ) { + if (!isFree(pos)) { + pos = blockEnds[pos]; + limit = pos + size; + if (limit >= end) { + return -1; + } continue; } - if (++freeSize == size) { + if (++pos == limit) { int blockEnd = pos + 1; int blockStart = blockEnd - size; - frees.set(blockStart, false); + clearFree(blockStart); blockEnds[blockStart] = blockEnd; this.mark = blockEnd; return blockStart; } - start++; } - return -1; } @Override protected void doStart() { Arrays.fill(blockEnds, 0); - this.frees.set(0, getCapacity(), true); + Arrays.fill(frees, -1); int cap = capacity * unit; - if (ENABLE_UNSAFE_BUF) { + if (Unsafe.UNSAFE_BUF_AVAILABLE) { this.address = Unsafe.allocate(cap); } else { if (isDirect()) { @@ -167,15 +163,42 @@ protected void doStart() { } } + private static int wordIndex(int bitIndex) { + return bitIndex >> ADDRESS_BITS_PER_WORD; + } + + private void setFree(int index) { + int wordIndex = wordIndex(index); + frees[wordIndex] |= (1L << index); + } + + private void clearFree(int index) { + int wordIndex = wordIndex(index); + frees[wordIndex] &= ~(1L << index); + } + + private boolean isFree(int index) { + int wordIndex = wordIndex(index); + return ((frees[wordIndex] & (1L << index)) != 0); + } + @Override protected void doStop() { - ReentrantLock lock = this.lock; - lock.lock(); - try { - freeMemory(); - } finally { - lock.unlock(); + for (; ; ) { + ReentrantLock lock = this.lock; + lock.lock(); + try { + // check all memory(buf) are backed + if (usedBuf() == 0) { + freeMemory(); + return; + } + } finally { + lock.unlock(); + } + Util.sleep(8); } + } @Override @@ -190,7 +213,7 @@ protected void expansion(ByteBuf buf, int cap) { int end = blockStart + size; int i = blockEnd; for (; i < end; ) { - if (!frees.get(i)) { + if (!isFree(i)) { break; } i++; @@ -202,9 +225,8 @@ protected void expansion(ByteBuf buf, int cap) { } blockEnds[blockStart] = end; buf.capacity((end - buf.unitOffset()) * unit); - buf.limit(buf.capacity()); } else { - frees.set(blockStart); + setFree(blockStart); int pos = allocate(mark, capacity, size); if (pos == -1) { pos = allocate(0, mark, size); @@ -212,36 +234,30 @@ protected void expansion(ByteBuf buf, int cap) { throw EXPANSION_FAILED; } } - int oldOffset = buf.offset(); - int oldPos = buf.absPos(); - int copy = oldPos - oldOffset; - buf.produce(pos, blockEnds[pos]); - if (ENABLE_UNSAFE_BUF) { - Unsafe.copyMemory(address + oldOffset, address + buf.offset(), copy); + int old_read_index = buf.readIndex(); + int old_write_index = buf.writeIndex(); + int old_offset = buf.offset(); + buf.produce(pos, size); + if (Unsafe.UNSAFE_BUF_AVAILABLE) { + Unsafe.copyMemory(address + old_offset, address + buf.offset(), old_write_index); } else { if (isDirect) { - Unsafe.copyMemory(address + oldOffset, address + buf.offset(), copy); + Unsafe.copyMemory(address + old_offset, address + buf.offset(), old_write_index); } else { - System.arraycopy(heapMemory, oldOffset, heapMemory, buf.offset(), copy); + System.arraycopy(heapMemory, old_offset, heapMemory, buf.offset(), old_write_index); } } - buf.position(copy); + buf.readIndex(old_read_index).writeIndex(old_write_index); } } finally { lock.unlock(); } - } else { - buf.limit(cap); } } @Override public void freeMemory() { - // check all memory(buf) are backed - for (; usedBuf() != 0; ) { - Util.sleep(8); - } - if (ENABLE_UNSAFE_BUF) { + if (Unsafe.UNSAFE_BUF_AVAILABLE) { Unsafe.free(address); } else { if (isDirect()) { @@ -287,10 +303,10 @@ public final int getUnit() { public ByteBuf getUsedBuf(int skip) { int skiped = 0; for (int i = 0; i < getCapacity(); i++) { - if (!frees.get(i)) { + if (!isFree(i)) { skiped++; if (skiped > skip) { - return newByteBuf().produce(i, blockEnds[i]); + return newByteBuf().produce(i, blockEnds[i] - i); } } } @@ -305,7 +321,7 @@ private int maxFree() { int free = 0; int maxFree = 0; for (int i = 0; i < getCapacity(); i++) { - if (frees.get(i)) { + if (isFree(i)) { free++; } else { maxFree = Math.max(maxFree, free); @@ -317,22 +333,23 @@ private int maxFree() { } private ByteBuf newByteBuf() { - if (BYTEBUF_RECYCLE) { - ByteBuf buf = bufBuffer.pop(); + if (BUF_POOL_ENABLE) { + ObjectPool pool = BUF_POOL.get(); + ByteBuf buf = pool.pop(); if (buf == null) { - return newByteBuf0(); + return newByteBuf0(pool); } return buf; } else { - return newByteBuf0(); + return newByteBuf0(ObjectPool.BLANK); } } - private ByteBuf newByteBuf0() { - if (ENABLE_UNSAFE_BUF) { - return new PooledUnsafeByteBuf(this, address); + private ByteBuf newByteBuf0(ObjectPool pool) { + if (Unsafe.UNSAFE_BUF_AVAILABLE) { + return new PooledUnsafeByteBuf(this, pool, address); } else { - return isDirect() ? new PooledDirectByteBuf(this, directMemory.duplicate()) : new PooledHeapByteBuf(this, heapMemory); + return isDirect() ? new PooledDirectByteBuf(this, pool, directMemory.duplicate()) : new PooledHeapByteBuf(this, pool, heapMemory); } } @@ -341,12 +358,12 @@ public void release(ByteBuf buf) { ReentrantLock lock = this.lock; lock.lock(); try { - frees.set(buf.unitOffset()); + setFree(buf.unitOffset()); } finally { lock.unlock(); } - if (BYTEBUF_RECYCLE) { - bufBuffer.push(buf); + if (BUF_POOL_ENABLE) { + buf.recycleObject(); } if (Develop.BUF_DEBUG && buf.isPooled()) { BufDebug d = BUF_DEBUGS.remove(buf); @@ -358,8 +375,7 @@ public void release(ByteBuf buf) { } } - @Override - public String toString() { + public String toDebugString() { ReentrantLock lock = this.lock; lock.lock(); try { @@ -388,7 +404,7 @@ public String toString() { private int usedBuf() { int used = 0; for (int i = 0; i < getCapacity(); i++) { - if (!frees.get(i)) { + if (!isFree(i)) { used++; } } @@ -398,7 +414,7 @@ private int usedBuf() { private int usedMem() { int used = 0; for (int i = 0; i < getCapacity(); i++) { - if (!frees.get(i)) { + if (!isFree(i)) { int next = blockEnds[i]; used += (next - i); i = next - 1; @@ -407,7 +423,14 @@ private int usedMem() { return used; } - public class BufDebug { + static Map NEW_BUF_DEBUGS() { + return Develop.BUF_DEBUG ? new ConcurrentHashMap() : null; + } + + /** + * for debug + */ + public static class BufDebug { public volatile ByteBuf buf; public volatile Exception e; @@ -417,7 +440,7 @@ public class BufDebug { /** * for debug */ - public class PoolState { + public static class PoolState { public int buf; public int free; public int memory; diff --git a/firenio-core/src/main/java/com/firenio/buffer/PooledDirectByteBuf.java b/firenio-core/src/main/java/com/firenio/buffer/PooledDirectByteBuf.java index c3bfeeb0d..536751897 100644 --- a/firenio-core/src/main/java/com/firenio/buffer/PooledDirectByteBuf.java +++ b/firenio-core/src/main/java/com/firenio/buffer/PooledDirectByteBuf.java @@ -17,15 +17,18 @@ import java.nio.ByteBuffer; +import com.firenio.collection.ObjectPool; + final class PooledDirectByteBuf extends DirectByteBuf { - private PooledByteBufAllocator allocator; - private int capacity; - private int offset; - private int unitOffset; + private final PooledByteBufAllocator allocator; + private final ObjectPool pool; + private int capacity; + private int unitOffset; - PooledDirectByteBuf(PooledByteBufAllocator allocator, ByteBuffer memory) { + PooledDirectByteBuf(PooledByteBufAllocator allocator, ObjectPool pool, ByteBuffer memory) { super(memory); + this.pool = pool; this.allocator = allocator; } @@ -44,15 +47,6 @@ protected void capacity(int cap) { this.capacity = cap; } - @Override - public ByteBuf duplicate() { - if (isReleased()) { - throw new IllegalStateException("released"); - } - addReferenceCount(); - return new DuplicatedByteBuf(memory.duplicate(), this, 1); - } - @Override public final void expansion(int cap) { allocator.expansion(this, cap); @@ -64,22 +58,12 @@ public boolean isPooled() { } @Override - protected int offset() { - return offset; - } - - @Override - protected void offset(int offset) { - this.offset = offset; - } - - @Override - protected ByteBuf produce(int unitOffset, int unitEnd) { + protected ByteBuf produce(int unitOffset, int unitSize) { int unit = allocator.getUnit(); this.offset = unitOffset * unit; - this.capacity = (unitEnd - unitOffset) * unit; - this.limit(capacity); - this.position(0); + this.capacity = unitSize * unit; + this.abs_read_index = offset; + this.abs_write_index = offset; this.unitOffset = unitOffset; this.referenceCount = 1; return this; @@ -100,4 +84,9 @@ protected void unitOffset(int unitOffset) { this.unitOffset = unitOffset; } + @Override + protected void recycleObject() { + pool.push(this); + } + } diff --git a/firenio-core/src/main/java/com/firenio/buffer/PooledHeapByteBuf.java b/firenio-core/src/main/java/com/firenio/buffer/PooledHeapByteBuf.java index abb49755c..c800c371e 100644 --- a/firenio-core/src/main/java/com/firenio/buffer/PooledHeapByteBuf.java +++ b/firenio-core/src/main/java/com/firenio/buffer/PooledHeapByteBuf.java @@ -15,15 +15,18 @@ */ package com.firenio.buffer; +import com.firenio.collection.ObjectPool; + final class PooledHeapByteBuf extends HeapByteBuf { - private PooledByteBufAllocator allocator; - private int capacity; - private int offset; - private int unitOffset; + private final PooledByteBufAllocator allocator; + private final ObjectPool pool; + private int capacity; + private int unitOffset; - PooledHeapByteBuf(PooledByteBufAllocator allocator, byte[] memory) { + PooledHeapByteBuf(PooledByteBufAllocator allocator, ObjectPool pool, byte[] memory) { super(memory); + this.pool = pool; this.allocator = allocator; } @@ -42,15 +45,6 @@ public void capacity(int cap) { this.capacity = cap; } - @Override - public ByteBuf duplicate() { - if (isReleased()) { - throw new IllegalStateException("released"); - } - addReferenceCount(); - return new DuplicatedByteBuf(nioBuffer().duplicate(), this, 1); - } - @Override public final void expansion(int cap) { allocator.expansion(this, cap); @@ -62,22 +56,12 @@ public boolean isPooled() { } @Override - protected int offset() { - return offset; - } - - @Override - protected void offset(int offset) { - this.offset = offset; - } - - @Override - protected PooledHeapByteBuf produce(int unitOffset, int unitEnd) { + protected PooledHeapByteBuf produce(int unitOffset, int unitSize) { int unit = allocator.getUnit(); this.offset = unitOffset * unit; - this.capacity = (unitEnd - unitOffset) * unit; - this.pos = offset; - this.limit = offset + capacity; + this.capacity = unitSize * unit; + this.abs_read_index = offset; + this.abs_write_index = offset; this.unitOffset = unitOffset; this.referenceCount = 1; return this; @@ -98,4 +82,9 @@ protected void unitOffset(int unitOffset) { this.unitOffset = unitOffset; } + @Override + protected void recycleObject() { + pool.push(this); + } + } diff --git a/firenio-core/src/main/java/com/firenio/buffer/PooledUnsafeByteBuf.java b/firenio-core/src/main/java/com/firenio/buffer/PooledUnsafeByteBuf.java index a44515e88..903b57e01 100644 --- a/firenio-core/src/main/java/com/firenio/buffer/PooledUnsafeByteBuf.java +++ b/firenio-core/src/main/java/com/firenio/buffer/PooledUnsafeByteBuf.java @@ -15,15 +15,18 @@ */ package com.firenio.buffer; +import com.firenio.collection.ObjectPool; + final class PooledUnsafeByteBuf extends UnsafeByteBuf { - private PooledByteBufAllocator allocator; - private int capacity; - private int offset; - private int unitOffset; + private final PooledByteBufAllocator allocator; + private final ObjectPool pool; + private int capacity; + private int unitOffset; - PooledUnsafeByteBuf(PooledByteBufAllocator allocator, long memory) { + PooledUnsafeByteBuf(PooledByteBufAllocator allocator, ObjectPool pool, long memory) { super(memory); + this.pool = pool; this.allocator = allocator; } @@ -42,15 +45,6 @@ protected void capacity(int cap) { this.capacity = cap; } - @Override - public ByteBuf duplicate() { - if (isReleased()) { - throw new IllegalStateException("released"); - } - addReferenceCount(); - return new DuplicatedUnsafeByteBuf(this, 1); - } - @Override public final void expansion(int cap) { allocator.expansion(this, cap); @@ -62,22 +56,12 @@ public boolean isPooled() { } @Override - protected int offset() { - return offset; - } - - @Override - protected void offset(int offset) { - this.offset = offset; - } - - @Override - protected ByteBuf produce(int unitOffset, int unitEnd) { + protected ByteBuf produce(int unitOffset, int unitSize) { int unit = allocator.getUnit(); this.offset = unitOffset * unit; - this.capacity = (unitEnd - unitOffset) * unit; - this.limit(capacity); - this.position(0); + this.capacity = unitSize * unit; + this.abs_read_index = offset; + this.abs_write_index = offset; this.unitOffset = unitOffset; this.referenceCount = 1; return this; @@ -98,4 +82,9 @@ protected void unitOffset(int unitOffset) { this.unitOffset = unitOffset; } + @Override + protected void recycleObject() { + pool.push(this); + } + } diff --git a/firenio-core/src/main/java/com/firenio/buffer/UnpooledByteBufAllocator.java b/firenio-core/src/main/java/com/firenio/buffer/UnpooledByteBufAllocator.java index 1c8dcabc5..a5bfccd98 100644 --- a/firenio-core/src/main/java/com/firenio/buffer/UnpooledByteBufAllocator.java +++ b/firenio-core/src/main/java/com/firenio/buffer/UnpooledByteBufAllocator.java @@ -15,26 +15,14 @@ */ package com.firenio.buffer; -public final class UnpooledByteBufAllocator extends ByteBufAllocator { - - private static final UnpooledByteBufAllocator directAlloc = new UnpooledByteBufAllocator(true); - private static final UnpooledByteBufAllocator heapAlloc = new UnpooledByteBufAllocator(false); - private final boolean isDirect; - - private UnpooledByteBufAllocator(boolean isDirect) { - this.isDirect = isDirect; - } +import com.firenio.common.Unsafe; - public static UnpooledByteBufAllocator get(boolean direct) { - return direct ? directAlloc : heapAlloc; - } +public final class UnpooledByteBufAllocator extends ByteBufAllocator { - public static UnpooledByteBufAllocator getDirect() { - return directAlloc; - } + static final UnpooledByteBufAllocator ALLOC = new UnpooledByteBufAllocator(); - public static UnpooledByteBufAllocator getHeap() { - return heapAlloc; + public static UnpooledByteBufAllocator get() { + return ALLOC; } @Override @@ -44,11 +32,7 @@ public ByteBuf allocate() { @Override public ByteBuf allocate(int capacity) { - if (isDirect()) { - return ByteBuf.direct(capacity); - } else { - return ByteBuf.heap(capacity); - } + return ByteBuf.buffer(capacity); } @Override @@ -76,7 +60,7 @@ public int getUnit() { } public boolean isDirect() { - return isDirect; + return Unsafe.DIRECT_BUFFER_AVAILABLE; } @Override diff --git a/firenio-core/src/main/java/com/firenio/buffer/UnpooledDirectByteBuf.java b/firenio-core/src/main/java/com/firenio/buffer/UnpooledDirectByteBuf.java index 80fed850f..3fbf845cf 100644 --- a/firenio-core/src/main/java/com/firenio/buffer/UnpooledDirectByteBuf.java +++ b/firenio-core/src/main/java/com/firenio/buffer/UnpooledDirectByteBuf.java @@ -29,39 +29,21 @@ final class UnpooledDirectByteBuf extends DirectByteBuf { this.referenceCount = 1; } - @Override - public long address() { - return Unsafe.address(memory); - } - @Override public int capacity() { return memory.capacity(); } - @Override - public ByteBuf duplicate() { - if (isReleased()) { - throw new IllegalStateException("released"); - } - //请勿移除此行,DirectByteBuffer需要手动回收,release要确保被执行 - addReferenceCount(); - return new DuplicatedByteBuf(memory.duplicate(), this, 1); - } - @Override public void expansion(int cap) { - ByteBuffer oldBuffer = memory; + ByteBuffer oldBuffer = getNioBuffer(); try { - ByteBuffer newBuffer = Unsafe.allocateDirectByteBuffer(cap); - int pos = oldBuffer.position(); - oldBuffer.position(0); - oldBuffer.limit(pos); - if (pos > 0) { - copy(Unsafe.address(oldBuffer) + oldBuffer.position(), Unsafe.address(newBuffer) + newBuffer.position(), pos); + ByteBuffer newBuffer = Unsafe.allocateDirectByteBuffer(cap); + int old_write_index = writeIndex(); + if (old_write_index > 0) { + copy(address(), Unsafe.address(newBuffer), old_write_index); } - newBuffer.position(pos); - memory = newBuffer; + setMemory(newBuffer); } finally { Unsafe.freeByteBuffer(oldBuffer); } @@ -77,4 +59,15 @@ protected void release0() { Unsafe.freeByteBuffer(memory); } + @Override + public void reset(ByteBuffer memory) { + if (!memory.isDirect()){ + throw unsupportedOperationException(); + } + this.referenceCount = 1; + this.setMemory(memory); + this.writeIndex(memory.limit()); + this.reverseRead(); + } + } diff --git a/firenio-core/src/main/java/com/firenio/buffer/UnpooledHeapByteBuf.java b/firenio-core/src/main/java/com/firenio/buffer/UnpooledHeapByteBuf.java index e70481dda..414784bba 100644 --- a/firenio-core/src/main/java/com/firenio/buffer/UnpooledHeapByteBuf.java +++ b/firenio-core/src/main/java/com/firenio/buffer/UnpooledHeapByteBuf.java @@ -24,14 +24,14 @@ class UnpooledHeapByteBuf extends HeapByteBuf { UnpooledHeapByteBuf(byte[] memory, int off, int len) { super(memory); - this.pos = off; - this.limit = off + len; + this.abs_read_index = off; + this.abs_write_index = off; } UnpooledHeapByteBuf(ByteBuffer memory) { super(memory); - this.pos = memory.position(); - this.limit = memory.limit(); + this.abs_read_index = memory.position(); + this.abs_write_index = memory.position(); } @Override @@ -44,20 +44,14 @@ public int capacity() { return memory.length; } - @Override - public ByteBuf duplicate() { - return new DuplicatedByteBuf(nioBuffer().duplicate(), this, 0); - } - @Override public void expansion(int cap) { byte[] oldBuffer = memory; byte[] newBuffer = new byte[cap]; - if (pos > 0) { - copy(oldBuffer, 0, newBuffer, 0, pos); + if (hasReadableBytes()) { + copy(oldBuffer, absReadIndex(), newBuffer, 0, readableBytes()); } memory = newBuffer; - limit = capacity(); } @Override @@ -68,6 +62,26 @@ public boolean isPooled() { @Override protected final void release0() {} + @Override + public void reset(ByteBuffer memory) { + if (memory.isDirect()) { + throw unsupportedOperationException(); + } + this.referenceCount = 1; + this.memory = memory.array(); + this.nioBuffer = memory; + this.writeIndex(memory.limit()); + this.reverseRead(); + } + + @Override + public void reset(byte[] memory, int off, int len) { + this.referenceCount = 1; + this.memory = memory; + this.readIndex(off); + this.writeIndex(off + len); + } + static final class EmptyByteBuf extends UnpooledHeapByteBuf { static final EmptyByteBuf EMPTY = new UnpooledHeapByteBuf.EmptyByteBuf(); @@ -86,6 +100,31 @@ public boolean isReleased() { return true; } + @Override + public void expansion(int cap) { + throw unsupportedOperationException(); + } + + @Override + public ByteBuf resetReadIndex() { + throw unsupportedOperationException(); + } + + @Override + public ByteBuf resetWriteIndex() { + throw unsupportedOperationException(); + } + + @Override + public ByteBuf readIndex(int index) { + throw unsupportedOperationException(); + } + + @Override + public ByteBuf writeIndex(int index) { + throw unsupportedOperationException(); + } + } } diff --git a/firenio-core/src/main/java/com/firenio/buffer/UnpooledUnsafeByteBuf.java b/firenio-core/src/main/java/com/firenio/buffer/UnpooledUnsafeByteBuf.java index 918aa694e..54724de73 100644 --- a/firenio-core/src/main/java/com/firenio/buffer/UnpooledUnsafeByteBuf.java +++ b/firenio-core/src/main/java/com/firenio/buffer/UnpooledUnsafeByteBuf.java @@ -15,6 +15,8 @@ */ package com.firenio.buffer; +import java.nio.ByteBuffer; + import com.firenio.common.Unsafe; /** @@ -22,30 +24,21 @@ */ final class UnpooledUnsafeByteBuf extends UnsafeByteBuf { + private int capacity; + UnpooledUnsafeByteBuf(long memory, int cap) { super(memory); this.capacity = cap; this.referenceCount = 1; } - @Override - public ByteBuf duplicate() { - if (isReleased()) { - throw new IllegalStateException("released"); - } - //请勿移除此行,DirectByteBuffer需要手动回收,release要确保被执行 - addReferenceCount(); - return new DuplicatedUnsafeByteBuf(this, 1); - } - @Override public void expansion(int cap) { long oldBuffer = memory; try { long newBuffer = Unsafe.allocate(cap); - int pos = absPos(); - if (pos > 0) { - copy(oldBuffer + pos, newBuffer, pos); + if (hasReadableBytes()) { + copy(oldBuffer + absReadIndex(), newBuffer, readableBytes()); } memory = newBuffer; } finally { @@ -53,6 +46,11 @@ public void expansion(int cap) { } } + @Override + public int capacity() { + return capacity; + } + @Override public boolean isPooled() { return false; @@ -63,4 +61,13 @@ protected void release0() { Unsafe.free(address()); } + @Override + public void reset(long memory, int capacity, int off, int len) { + this.referenceCount = 1; + this.setMemory(memory); + this.capacity = capacity; + this.readIndex(off); + this.writeIndex(off + len); + } + } diff --git a/firenio-core/src/main/java/com/firenio/buffer/UnsafeByteBuf.java b/firenio-core/src/main/java/com/firenio/buffer/UnsafeByteBuf.java index 090539c6a..917a86fe0 100644 --- a/firenio-core/src/main/java/com/firenio/buffer/UnsafeByteBuf.java +++ b/firenio-core/src/main/java/com/firenio/buffer/UnsafeByteBuf.java @@ -22,105 +22,128 @@ abstract class UnsafeByteBuf extends ByteBuf { - protected int capacity; - protected int limit; - protected int markLimit; - protected int markPos; protected long memory; - protected int pos; UnsafeByteBuf(long memory) { this.memory = memory; } @Override - public byte absByte(int pos) { - return Unsafe.getByte(memory + pos); + public long address() { + return memory; } @Override - public int absLimit() { - return limit; + public byte[] array() { + return null; } @Override - public ByteBuf absLimit(int limit) { - this.limit = limit; - return this; + public void compact() { + if (!hasReadableBytes()) { + clear(); + return; + } + long address = address(); + int remain = readableBytes(); + int abs_read_index = absReadIndex(); + int abs_write_index = absWriteIndex(); + long src_addr = address + abs_read_index; + long dst_addr = address + offset(); + Unsafe.copyMemory(src_addr, dst_addr, remain); + readIndex(0); + writeIndex(remain); } @Override - public int absPos() { - return pos; + public ByteBuf duplicate() { + if (isReleased()) { + throw new IllegalStateException("released"); + } + this.retain(); + return new DuplicatedUnsafeByteBuf(this, 1); } @Override - public ByteBuf absPos(int pos) { - this.pos = pos; - return this; + public byte getByteAbs(int pos) { + return Unsafe.getByte(memory + pos); } @Override - public long address() { - return memory; + public void getBytes(int index, byte[] dst, int offset, int length) { + Unsafe.copyToArray(memory + ix(index), dst, offset, length); } @Override - public byte[] array() { - return null; + protected int getBytes0(int index, ByteBuf dst, int len) { + if (dst.hasArray()) { + copy(address() + ix(index), dst.array(), dst.writeIndex(), len); + } else { + copy(address() + ix(index), dst.address() + dst.absWriteIndex(), len); + } + dst.skipWrite(len); + return len; } @Override - public int capacity() { - return capacity; + protected int getBytes0(int index, ByteBuffer dst, int len) { + if (dst.hasArray()) { + copy(address() + ix(index), dst.array(), dst.position(), len); + } else { + copy(address() + ix(index), Unsafe.address(dst) + dst.position(), len); + } + dst.position(dst.position() + len); + return len; } @Override - public ByteBuf clear() { - this.pos = offset(); - this.limit = ix(capacity()); - return this; + public void readBytes(byte[] dst, int offset, int length) { + Unsafe.copyToArray(memory + absReadIndex(), dst, offset, length); + this.skipRead(length); } @Override - public ByteBuf flip() { - this.limit = pos; - this.pos = offset(); - return this; + protected int readBytes0(ByteBuf dst, int len) { + if (dst.hasArray()) { + copy(address() + absReadIndex(), dst.array(), dst.writeIndex(), len); + } else { + copy(address() + absReadIndex(), dst.address() + dst.absWriteIndex(), len); + } + dst.skipWrite(len); + skipRead(len); + return len; } @Override - protected int get0(ByteBuffer dst, int len) { + protected int readBytes0(ByteBuffer dst, int len) { if (dst.hasArray()) { - copy(address() + absPos(), dst.array(), dst.position(), len); + copy(address() + absReadIndex(), dst.array(), dst.position(), len); } else { - copy(address() + absPos(), Unsafe.address(dst) + dst.position(), len); + copy(address() + absReadIndex(), Unsafe.address(dst) + dst.position(), len); } dst.position(dst.position() + len); - skip(len); + skipRead(len); return len; } - @Override - public byte getByte() { - return Unsafe.getByte(address() + (pos++)); + protected void setMemory(long memory) { + this.memory = memory; } @Override - public byte getByte(int index) { - return Unsafe.getByte(address() + ix(index)); + public byte readByte() { + return Unsafe.getByte(address() + abs_read_index++); } @Override - public void getBytes(byte[] dst, int offset, int length) { - Unsafe.copyToArray(memory + absPos(), dst, offset, length); - this.skip(length); + public byte getByte(int index) { + return Unsafe.getByte(address() + ix(index)); } @Override - public int getInt() { - int v = ByteUtil.getInt(address() + absPos()); - this.skip(4); + public int readInt() { + int v = ByteUtil.getInt(address() + absReadIndex()); + this.skipRead(4); return v; } @@ -130,9 +153,9 @@ public int getInt(int index) { } @Override - public int getIntLE() { - int v = ByteUtil.getIntLE(address() + absPos()); - this.skip(4); + public int readIntLE() { + int v = ByteUtil.getIntLE(address() + absReadIndex()); + this.skipRead(4); return v; } @@ -142,9 +165,9 @@ public int getIntLE(int index) { } @Override - public long getLong() { - long v = ByteUtil.getLong(address() + absPos()); - this.skip(8); + public long readLong() { + long v = ByteUtil.getLong(address() + absReadIndex()); + this.skipRead(8); return v; } @@ -154,9 +177,9 @@ public long getLong(int index) { } @Override - public long getLongLE() { - long v = ByteUtil.getLongLE(address() + absPos()); - this.skip(8); + public long readLongLE() { + long v = ByteUtil.getLongLE(address() + absReadIndex()); + this.skipRead(8); return v; } @@ -167,13 +190,13 @@ public long getLongLE(int index) { @Override public ByteBuffer getNioBuffer() { - return null; + throw unsupportedOperationException(); } @Override - public short getShort() { - short v = ByteUtil.getShort(address() + absPos()); - this.skip(2); + public short readShort() { + short v = ByteUtil.getShort(address() + absReadIndex()); + this.skipRead(2); return v; } @@ -183,9 +206,9 @@ public short getShort(int index) { } @Override - public short getShortLE() { - short v = ByteUtil.getShortLE(address() + absPos()); - this.skip(2); + public short readShortLE() { + short v = ByteUtil.getShortLE(address() + absReadIndex()); + this.skipRead(2); return v; } @@ -195,8 +218,8 @@ public short getShortLE(int index) { } @Override - public short getUnsignedByte() { - return (short) (getByte() & 0xff); + public short readUnsignedByte() { + return (short) (readByte() & 0xff); } @Override @@ -205,31 +228,31 @@ public short getUnsignedByte(int index) { } @Override - public long getUnsignedInt() { - return getInt() & 0xffffffffL; + public long readUnsignedInt() { + return toUnsignedInt(readInt()); } @Override public long getUnsignedInt(int index) { - return getInt(index) & 0xffffffffL; + return toUnsignedInt(getInt(index)); } @Override - public long getUnsignedIntLE() { - long v = ByteUtil.getIntLE(address() + absPos()) & 0xffffffffL; - this.skip(4); + public long readUnsignedIntLE() { + long v = toUnsignedInt(ByteUtil.getIntLE(address() + absReadIndex())); + this.skipRead(4); return v; } @Override public long getUnsignedIntLE(int index) { - return ByteUtil.getIntLE(address() + ix(index)) & 0xffffffffL; + return toUnsignedInt(ByteUtil.getIntLE(address() + ix(index))); } @Override - public int getUnsignedShort() { - int v = ByteUtil.getShort(address() + absPos()) & 0xffff; - this.skip(2); + public int readUnsignedShort() { + int v = ByteUtil.getShort(address() + absReadIndex()) & 0xffff; + this.skipRead(2); return v; } @@ -239,9 +262,9 @@ public int getUnsignedShort(int index) { } @Override - public int getUnsignedShortLE() { - int v = ByteUtil.getShortLE(address() + absPos()) & 0xffff; - this.skip(2); + public int readUnsignedShortLE() { + int v = ByteUtil.getShortLE(address() + absReadIndex()) & 0xffff; + this.skipRead(2); return v; } @@ -255,11 +278,6 @@ public boolean hasArray() { return false; } - @Override - public boolean hasRemaining() { - return pos < limit; - } - @Override public int indexOf(byte b, int abs_pos, int size) { long addr = address(); @@ -287,177 +305,145 @@ public int lastIndexOf(byte b, int abs_pos, int size) { } @Override - public int limit() { - return limit - offset(); - } - - @Override - public ByteBuf limit(int limit) { - this.limit = ix(limit); - return this; - } - - @Override - public ByteBuf markL() { - markLimit = limit; - return this; - } - - @Override - public ByteBuf markP() { - markPos = pos; - return this; - } - - @Override - public ByteBuffer nioBuffer() { - ByteBuffer buffer = getNioBuffer(); - return (ByteBuffer) buffer.limit(limit).position(pos); + public void setByte(int index, byte b) { + Unsafe.putByte(address() + ix(index), b); } @Override - public int position() { - return pos - offset(); + protected void writeByte0(byte b) { + Unsafe.putByte(address() + abs_write_index++, b); } @Override - public ByteBuf position(int position) { - this.pos = ix(position); - return this; + protected int setBytes0(int index, byte[] src, int offset, int length) { + Unsafe.copyFromArray(src, offset, address() + ix(index), length); + return length; } @Override - public void putByte(int index, byte b) { - Unsafe.putByte(address() + ix(index), b); + protected int setBytes0(int index, ByteBuf src, int len) { + if (src.hasArray()) { + copy(src.array(), src.absReadIndex(), address() + ix(index), len); + } else { + copy(src.address() + src.absReadIndex(), address() + ix(index), len); + } + src.skipRead(len); + return len; } @Override - protected void putByte0(byte b) { - Unsafe.putByte(address() + (pos++), b); + protected int setBytes0(int index, ByteBuffer src, int len) { + if (src.hasArray()) { + copy(src.array(), src.position(), address() + ix(index), len); + } else { + copy(Unsafe.address(src) + src.position(), address() + ix(index), len); + } + src.position(src.position() + len); + return len; } @Override - protected int putBytes0(byte[] src, int offset, int length) { - Unsafe.copyFromArray(src, offset, address() + absPos(), length); - this.pos += length; + protected int writeBytes0(byte[] src, int offset, int length) { + Unsafe.copyFromArray(src, offset, address() + absWriteIndex(), length); + skipWrite(length); return length; } @Override - protected int putBytes00(ByteBuf src, int len) { + protected int writeBytes0(ByteBuf src, int len) { if (src.hasArray()) { - copy(src.array(), src.absPos(), address() + absPos(), len); + copy(src.array(), src.absReadIndex(), address() + absWriteIndex(), len); } else { - copy(src.address() + src.absPos(), address() + absPos(), len); + copy(src.address() + src.absReadIndex(), address() + absWriteIndex(), len); } - src.skip(len); - skip(len); + src.skipRead(len); + skipWrite(len); return len; } @Override - protected int putBytes00(ByteBuffer src, int len) { + protected int writeBytes0(ByteBuffer src, int len) { if (src.hasArray()) { - copy(src.array(), src.position(), address() + absPos(), len); + copy(src.array(), src.position(), address() + absWriteIndex(), len); } else { - copy(Unsafe.address(src) + src.position(), address() + absPos(), len); + copy(Unsafe.address(src) + src.position(), address() + absWriteIndex(), len); } src.position(src.position() + len); - skip(len); + skipWrite(len); return len; } @Override - public void putInt(int index, int value) { + public void setInt(int index, int value) { ByteUtil.putInt(address() + ix(index), value); } @Override - protected void putInt0(int value) { - ByteUtil.putInt(address() + absPos(), value); - skip(4); + protected void writeInt0(int value) { + ByteUtil.putInt(address() + absWriteIndex(), value); + skipWrite(4); } @Override - public void putIntLE(int index, int value) { + public void setIntLE(int index, int value) { ByteUtil.putIntLE(address() + ix(index), value); } @Override - protected void putIntLE0(int value) { - ByteUtil.putIntLE(address() + absPos(), value); - skip(4); + protected void writeIntLE0(int value) { + ByteUtil.putIntLE(address() + absWriteIndex(), value); + skipWrite(4); } @Override - public void putLong(int index, long value) { + public void setLong(int index, long value) { ByteUtil.putLong(address() + ix(index), value); } @Override - protected void putLong0(long value) { - ByteUtil.putLong(address() + absPos(), value); - skip(8); + protected void writeLong0(long value) { + ByteUtil.putLong(address() + absWriteIndex(), value); + skipWrite(8); } @Override - public void putLongLE(int index, long value) { + public void setLongLE(int index, long value) { ByteUtil.putLongLE(address() + ix(index), value); } @Override - protected void putLongLE0(long value) { - ByteUtil.putLongLE(address() + absPos(), value); - skip(8); + protected void writeLongLE0(long value) { + ByteUtil.putLongLE(address() + absWriteIndex(), value); + skipWrite(8); } @Override - public void putShort(int index, int value) { + public void setShort(int index, int value) { ByteUtil.putShort(address() + ix(index), (short) value); } @Override - protected void putShort0(int value) { - ByteUtil.putShort(address() + absPos(), (short) value); - skip(2); + protected void writeShort0(int value) { + ByteUtil.putShort(address() + absWriteIndex(), (short) value); + skipWrite(2); } @Override - public void putShortLE(int index, int value) { + public void setShortLE(int index, int value) { ByteUtil.putShortLE(address() + ix(index), (short) value); } @Override - protected void putShortLE0(int value) { - ByteUtil.putShortLE(address() + absPos(), (short) value); - skip(2); - } - - @Override - public int remaining() { - return limit - pos; + protected void writeShortLE0(int value) { + ByteUtil.putShortLE(address() + absWriteIndex(), (short) value); + skipWrite(2); } - @Override - public ByteBuf resetL() { - limit = markLimit; - return this; - } - - @Override - public ByteBuf resetP() { - pos = markPos; + public ByteBuf reverseRead() { return this; } - @Override - public ByteBuf reverse() { - return this; - } - - @Override - public ByteBuf skip(int length) { - pos += length; + public ByteBuf reverseWrite() { return this; } diff --git a/firenio-core/src/main/java/com/firenio/collection/AttributeKey.java b/firenio-core/src/main/java/com/firenio/collection/AttributeKey.java new file mode 100644 index 000000000..c62062a09 --- /dev/null +++ b/firenio-core/src/main/java/com/firenio/collection/AttributeKey.java @@ -0,0 +1,54 @@ +/* + * Copyright 2015 The FireNio Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.firenio.collection; + +import com.firenio.collection.AttributeMap.AttributeInitFunction; + +/** + * @author: wangkai + **/ +public final class AttributeKey { + + private final int index; + + private final String name; + + private final AttributeInitFunction function; + + AttributeKey(int index, String name, AttributeInitFunction function) { + this.name = name; + this.index = index; + this.function = function; + } + + public int getIndex() { + return index; + } + + public String getName() { + return name; + } + + public AttributeInitFunction getFunction() { + return function; + } + + @Override + public String toString() { + return "name: " + name + ", index: " + index; + } + +} diff --git a/firenio-core/src/main/java/com/firenio/collection/AttributeMap.java b/firenio-core/src/main/java/com/firenio/collection/AttributeMap.java new file mode 100644 index 000000000..d60515a57 --- /dev/null +++ b/firenio-core/src/main/java/com/firenio/collection/AttributeMap.java @@ -0,0 +1,150 @@ +/* + * Copyright 2015 The FireNio Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.firenio.collection; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * use for static variable, eg: + *
+ * static final AttributeKey KEY_NAME = AttributeMap.valueOfKey(Channel.class, "KEY_NAME");
+ * 
+ */
+//TODO 考虑多个ChannelContext时,每个Context里Channel存储的数据key不一样,会造成内存浪费
+public abstract class AttributeMap {
+
+    private static final Map, AttributeKeys> INDEX_MAPPING = new ConcurrentHashMap<>();
+
+    private final Object[] attributes;
+
+    private volatile int memoryBarrier = 0;
+
+    public AttributeMap() {
+        AttributeKeys keys = getKeys();
+        if (keys == null) {
+            attributes = null;
+            return;
+        }
+        keys.initialized = true;
+        this.attributes = new Object[keys.getCounter()];
+        for (AttributeKey key : keys.keys.values()) {
+            AttributeInitFunction function = key.getFunction();
+            function.setValue(this, key.getIndex());
+        }
+    }
+
+    public  T getAttribute(AttributeKey key) {
+        return (T) getAttribute(key.getIndex());
+    }
+
+    public  T getAttributeUnsafe(AttributeKey key) {
+        return (T) getAttributeUnsafe(key.getIndex());
+    }
+
+    public Object getAttribute(int key) {
+        memoryBarrier = 1;
+        return attributes[key];
+    }
+
+    public Object getAttributeUnsafe(int key) {
+        return attributes[key];
+    }
+
+    public void setAttribute(AttributeKey key, Object value) {
+        attributes[key.getIndex()] = value;
+    }
+
+    public void setAttribute(int key, Object value) {
+        memoryBarrier = 1;
+        attributes[key] = value;
+    }
+
+    public void setAttributeUnsafe(int key, Object value) {
+        attributes[key] = value;
+    }
+
+    public static AttributeKeys getKeys(Class clazz) {
+        return INDEX_MAPPING.get(clazz);
+    }
+
+    public static AttributeKey valueOfKey(Class clazz, String name) {
+        return valueOfKey(clazz, name, null);
+    }
+
+    public static AttributeKey valueOfKey(Class clazz, String name, AttributeInitFunction function) {
+        AttributeKeys attributeKeys = INDEX_MAPPING.get(clazz);
+        if (attributeKeys == null) {
+            synchronized (INDEX_MAPPING) {
+                attributeKeys = INDEX_MAPPING.get(clazz);
+                if (attributeKeys == null) {
+                    attributeKeys = new AttributeKeys();
+                    INDEX_MAPPING.put(clazz, attributeKeys);
+                }
+            }
+        }
+        return attributeKeys.valueOf(name, function);
+    }
+
+    protected int getMemoryBarrier() {
+        return memoryBarrier;
+    }
+
+    protected abstract AttributeKeys getKeys();
+
+    public static class AttributeKeys {
+
+        final Map keys    = new HashMap<>();
+        final Map ro_keys = Collections.unmodifiableMap(keys);
+
+        int counter = 0;
+        volatile boolean initialized = false;
+
+        synchronized AttributeKey valueOf(String name, AttributeInitFunction function) {
+            if (initialized) {
+                throw new RuntimeException("incorrect usage, AttributeKey can only be static constant");
+            }
+            if (function == null) {
+                function = NULL_VALUE_ATTRIBUTE_INIT_FUNCTION;
+            }
+            keys.put(name, new AttributeKey(counter++, name, function));
+            return keys.get(name);
+        }
+
+        public Map getKeys() {
+            return ro_keys;
+        }
+
+        public int getCounter() {
+            return counter;
+        }
+
+    }
+
+    public interface AttributeInitFunction {
+
+        void setValue(AttributeMap map, int key);
+
+    }
+
+    static final AttributeInitFunction NULL_VALUE_ATTRIBUTE_INIT_FUNCTION = new AttributeInitFunction() {
+        @Override
+        public void setValue(AttributeMap map, int key) { }
+    };
+
+}
diff --git a/firenio-core/src/main/java/com/firenio/collection/AttributesImpl.java b/firenio-core/src/main/java/com/firenio/collection/AttributesImpl.java
deleted file mode 100644
index d5d6f5f04..000000000
--- a/firenio-core/src/main/java/com/firenio/collection/AttributesImpl.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2015 The FireNio Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.firenio.collection;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-public class AttributesImpl implements Attributes {
-
-    private final Map attributes = new HashMap<>();
-
-    @Override
-    public Map attributes() {
-        return attributes;
-    }
-
-    @Override
-    public void clearAttributes() {
-        this.attributes.clear();
-    }
-
-    @Override
-    public Object getAttribute(Object key) {
-        return this.attributes.get(key);
-    }
-
-    @Override
-    public Set getAttributeNames() {
-        return this.attributes.keySet();
-    }
-
-    @Override
-    public Object removeAttribute(Object key) {
-        return this.attributes.remove(key);
-    }
-
-    @Override
-    public void setAttribute(Object key, Object value) {
-        this.attributes.put(key, value);
-    }
-
-}
diff --git a/firenio-core/src/main/java/com/firenio/collection/IntArray.java b/firenio-core/src/main/java/com/firenio/collection/IntArray.java
index 7f3b32dc2..bb07bdd3c 100644
--- a/firenio-core/src/main/java/com/firenio/collection/IntArray.java
+++ b/firenio-core/src/main/java/com/firenio/collection/IntArray.java
@@ -17,6 +17,9 @@
 
 import java.util.Arrays;
 
+import com.firenio.common.ByteUtil;
+import com.firenio.common.Util;
+
 /**
  * @author wangkai
  */
@@ -63,4 +66,9 @@ public boolean isEmpty() {
     public int size() {
         return size;
     }
+
+    @Override
+    public String toString() {
+        return Util.arrayToString(array, 0, size);
+    }
 }
diff --git a/firenio-core/src/main/java/com/firenio/collection/IntMap.java b/firenio-core/src/main/java/com/firenio/collection/IntMap.java
index 4e7d29650..7aa1a4f03 100644
--- a/firenio-core/src/main/java/com/firenio/collection/IntMap.java
+++ b/firenio-core/src/main/java/com/firenio/collection/IntMap.java
@@ -24,14 +24,16 @@
  */
 public final class IntMap {
 
+    static final float DEFAULT_LOAD_FACTOR = 0.5f;
+
     private final float loadFactor;
     private       int   cap;
     private       int[] keys;
     private       V[]   values;
-    private       int   scanSize;
+    private       int   scan_size;
     private       int   size;
     private       int   mask;
-    private       int   scanIndex;
+    private       int   scan_index;
     private       int   limit;
 
     public IntMap() {
@@ -39,7 +41,7 @@ public IntMap() {
     }
 
     public IntMap(int cap) {
-        this(cap, 0.75f);
+        this(cap, DEFAULT_LOAD_FACTOR);
     }
 
     @SuppressWarnings("unchecked")
@@ -48,117 +50,103 @@ public IntMap(int cap, float loadFactor) {
         int c = Util.clothCover(cap);
         this.cap = c;
         this.mask = c - 1;
-        this.loadFactor = Math.min(loadFactor, 0.75f);
+        this.loadFactor = loadFactor;
         this.keys = new int[c];
         this.values = (V[]) new Object[c];
         this.limit = (int) (c * loadFactor);
         Arrays.fill(keys, -1);
     }
 
-    private static int indexOfKey(int[] keys, int key, int mask) {
-        int index = key & mask;
-        if (keys[index] == key) {
-            return index;
-        }
-        for (int i = index, cnt = keys.length; i < cnt; i++) {
-            if (keys[i] == key) {
-                return i;
-            }
-        }
-        for (int i = 1; i < index; i++) {
-            if (keys[i] == key) {
-                return i;
-            }
-        }
-        //will not happen
-        return -1;
-
-    }
-
-    private static int indexOfFreeKey(int[] keys, int key, int mask) {
-        int index = key & mask;
-        int _key  = keys[index];
-        if (_key == -1 || _key == key) {
-            return index;
-        }
-        for (int i = index, cnt = keys.length; i < cnt; i++) {
-            _key = keys[i];
-            if (_key == -1 || _key == key) {
-                return i;
-            }
-        }
-        for (int i = 1; i < index; i++) {
-            _key = keys[i];
-            if (_key == -1 || _key == key) {
-                return i;
-            }
-        }
-        //will not happen
-        return -1;
-
-    }
-
+    /**
+     * DO NOT REMOVE while scan
+     */
     public void scan() {
-        this.scanSize = 0;
-        this.scanIndex = -1;
-    }
-
-    public boolean hasNext() {
-        return scanSize < size;
+        this.scan_size = 0;
+        this.scan_index = -1;
     }
 
     public V putIfAbsent(int key, V value) {
-        return putVal(key, value, true);
-    }
-
-    private V putVal(int key, V value, boolean absent) {
-        V res = put0(key, value, mask, keys, values, absent);
-        if (res == null) {
-            grow();
-            return null;
+        V v = get(key);
+        if (v == null) {
+            v = put(key, value);
         }
-        return res;
+        return v;
     }
 
     public V put(int key, V value) {
-        return putVal(key, value, false);
-    }
-
-    private int scan(int[] keys, int index) {
-        for (int i = index + 1, cnt = keys.length; i < cnt; i++) {
-            if (keys[i] != -1) {
-                return i;
+        V[]   values      = this.values;
+        int[] keys        = this.keys;
+        int   mask        = this.mask;
+        int   start_index = key & mask;
+        int   index       = start_index;
+        for (; ; ) {
+            int _key = keys[index & mask];
+            if (_key == -1) {
+                keys[index] = key;
+                values[index] = value;
+                grow();
+                return null;
+            } else if (_key == key) {
+                V old = values[index];
+                values[index] = value;
+                return old;
+            }
+            if ((index = next_key(index, mask)) == start_index) {
+                throw new IllegalStateException("failed to put");
             }
         }
-        return keys.length;
     }
 
-    public int next() {
-        int scanIndex = scan(keys, this.scanIndex);
-        if (scanIndex == cap) {
-            return scanIndex;
+    private static int next_key(int key, int mask) {
+        return (key + 1) & mask;
+    }
+
+    private void put(int[] keys, V[] values, int key, V value, int mask) {
+        int start_index = key & mask;
+        int index       = start_index;
+        for (; ; ) {
+            int _key = keys[index & mask];
+            if (_key == -1) {
+                keys[index] = key;
+                values[index] = value;
+                break;
+            } else if (_key == key) {
+                values[index] = value;
+                break;
+            }
+            if ((index = next_key(index, mask)) == start_index) {
+                throw new IllegalStateException("failed to put");
+            }
         }
-        this.scanIndex = scanIndex;
-        this.scanSize++;
-        return scanIndex;
     }
 
-    public int nextKey() {
-        next();
-        return key();
+    public boolean hasNext() {
+        return next() != -1;
     }
 
-    public V nextValue() {
-        next();
-        return value();
+    private int next() {
+        if (scan_size < size) {
+            int[] keys  = this.keys;
+            int   index = this.scan_index + 1;
+            int   cap   = this.cap;
+            for (; index < cap; index++) {
+                if (keys[index] != -1) {
+                    break;
+                }
+            }
+            this.scan_size++;
+            this.scan_index = index;
+            return index;
+        }
+        return -1;
     }
 
     public int key() {
-        return keys[scanIndex];
+        return keys[scan_index];
     }
 
     public V value() {
-        return values[scanIndex];
+        return values[scan_index];
     }
 
     public int indexKey(int index) {
@@ -169,38 +157,27 @@ public V indexValue(int index) {
         return values[index];
     }
 
-    private V put0(int key, V value, int mask, int[] keys, V[] values, boolean absent) {
-        int index = indexOfFreeKey(keys, key, mask);
-        if (keys[index] == key) {
-            if (absent) {
-                return values[index];
-            } else {
-                V old = values[index];
-                values[index] = value;
-                return old;
-            }
-        } else {
-            keys[index] = key;
-            values[index] = value;
-            return null;
-        }
-    }
-
     @SuppressWarnings("unchecked")
     private void grow() {
         size++;
         if (size > limit) {
-            int   cap      = Util.clothCover(this.cap + 1);
+            int   cap    = Util.clothCover(this.cap + 1);
             int   mask   = cap - 1;
             int[] keys   = new int[cap];
             V[]   values = (V[]) new Object[cap];
             int   limit  = (int) (cap * loadFactor);
             Arrays.fill(keys, -1);
             scan();
-            for (; hasNext(); ) {
+            int size = 0;
+            for (; ; ) {
                 int index = next();
-                put0(indexKey(index), indexValue(index), mask, keys, values, false);
+                if (index == -1) {
+                    break;
+                }
+                size++;
+                put(keys, values, indexKey(index), indexValue(index), mask);
             }
+            assert size == this.size;
             this.cap = cap;
             this.mask = mask;
             this.keys = keys;
@@ -210,26 +187,69 @@ private void grow() {
     }
 
     public V get(int key) {
-        int index = indexOfKey(keys, key, mask);
-        if (index == -1) {
-            return null;
+        int[] keys        = this.keys;
+        int   mask        = this.mask;
+        int   start_index = key & mask;
+        int   index       = start_index;
+        for (; ; ) {
+            int _key = keys[index & mask];
+            if (_key == -1) {
+                return null;
+            } else if (_key == key) {
+                return values[index];
+            }
+            if ((index = next_key(index, mask)) == start_index) {
+                return null;
+            }
         }
-        return values[index];
     }
 
-    public V remove(int key) {
-        int index = indexOfKey(keys, key, mask);
-        if (index == -1) {
-            return null;
+    // ref from IdentityHashMap
+    private void remove_at(int[] keys, V[] values, final int index, int mask) {
+        // Adapted from Knuth Section 6.4 Algorithm R
+        // Look for items to swap into newly vacated slot
+        // starting at index immediately following deletion,
+        // and continuing until a null slot is seen, indicating
+        // the end of a run of possibly-colliding keys.
+        for (int i = next_key(index, mask), key, next = index; (key = keys[i]) != -1; i = next_key(i, mask)) {
+            // The following test triggers if the item at slot i (which
+            // hashes to be at slot r) should take the spot vacated by d.
+            // If so, we swap it in, and then continue with d now at the
+            // newly vacated i.  This process will terminate when we hit
+            // the null slot at the end of this run.
+            // The test is messy because we are using a circular table.
+            int r = key & mask;
+            if ((i < r && (r <= next || next <= i)) || (r <= next && next <= i)) {
+                keys[next] = key;
+                values[next] = values[i];
+                keys[i] = -1;
+                values[i] = null;
+                next = i;
+            }
         }
-        V v = values[index];
-        values[index] = null;
-        keys[index] = -1;
-        size--;
-        if (index <= scanIndex) {
-            scanSize--;
+    }
+
+    public V remove(int key) {
+        int[] keys        = this.keys;
+        int   mask        = this.mask;
+        int   start_index = key & mask;
+        int   index       = start_index;
+        for (; ; ) {
+            int _key = keys[index & mask];
+            if (_key == -1) {
+                return null;
+            } else if (_key == key) {
+                size--;
+                V value = values[index];
+                keys[index] = -1;
+                values[index] = null;
+                remove_at(keys, values, index, mask);
+                return value;
+            }
+            if ((index = next_key(index, mask)) == start_index) {
+                return null;
+            }
         }
-        return v;
     }
 
     public String toString() {
@@ -250,9 +270,12 @@ public String toString() {
     public int conflict() {
         int s = 0;
         scan();
-        for (; hasNext(); ) {
+        for (; ; ) {
             int index = next();
-            if ((keys[index] & mask) != index) {
+            if (index == -1) {
+                break;
+            }
+            if ((key() & mask) != index) {
                 s++;
             }
         }
diff --git a/firenio-core/src/main/java/com/firenio/collection/ObjectPool.java b/firenio-core/src/main/java/com/firenio/collection/ObjectPool.java
new file mode 100644
index 000000000..0130f7d20
--- /dev/null
+++ b/firenio-core/src/main/java/com/firenio/collection/ObjectPool.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.firenio.collection;
+
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * @author: wangkai
+ **/
+public class ObjectPool {
+
+    public static final ObjectPool BLANK = new BlankObjectPool<>();
+
+    private       int      size;
+    private final int      capacity;
+    private final T[]      elements;
+    private final Thread   ownerThread;
+    private final Queue conElements = new ConcurrentLinkedQueue<>();
+
+    ObjectPool() {
+        this.ownerThread = null;
+        this.elements = null;
+        this.capacity = 0;
+        this.size = 0;
+    }
+
+    public ObjectPool(Thread ownerThread, int capacity) {
+        this.capacity = capacity;
+        this.ownerThread = ownerThread;
+        this.elements = (T[]) new Object[capacity];
+    }
+
+    private void initElements(T[] elements, InitValueFunction fun) {
+        for (int i = 0; i < elements.length; i++) {
+            elements[i] = fun.newItem(this);
+        }
+    }
+
+    public T pop() {
+        if (size > 0) {
+            return elements[--size];
+        }
+        return conElements.poll();
+    }
+
+    public void push(T t) {
+        Thread currentThread = Thread.currentThread();
+        if (currentThread == ownerThread) {
+            if (size < capacity) {
+                elements[size++] = t;
+            }
+        } else {
+            conElements.offer(t);
+        }
+    }
+
+    public int capacity() {
+        return capacity;
+    }
+
+    private interface InitValueFunction {
+
+        T newItem(ObjectPool pool);
+    }
+
+    static class BlankObjectPool extends ObjectPool {
+
+        @Override
+        public T pop() {
+            return null;
+        }
+
+        @Override
+        public void push(T t) { }
+
+        @Override
+        public int capacity() {
+            return 0;
+        }
+    }
+
+}
diff --git a/firenio-core/src/main/java/com/firenio/common/Assert.java b/firenio-core/src/main/java/com/firenio/common/Assert.java
index cff59a7e7..bae556f1c 100644
--- a/firenio-core/src/main/java/com/firenio/common/Assert.java
+++ b/firenio-core/src/main/java/com/firenio/common/Assert.java
@@ -25,15 +25,17 @@ public static void expectFalse(boolean expression) {
     }
 
     public static void expectFalse(boolean expression, String message) {
-        if (expression) {
-            throw new IllegalArgumentException(message);
-        }
+        expectTrue(!expression, message);
     }
 
     public static void expectTrue(boolean expression) {
         expectTrue(expression, "expression must be true");
     }
 
+    public static void expectEquals(Object a, Object b) {
+        expectFalse(a == null || !a.equals(b), "expression must be Equals");
+    }
+
     public static void expectTrue(boolean expression, String message) {
         if (!expression) {
             throw new IllegalArgumentException(message);
diff --git a/firenio-core/src/main/java/com/firenio/common/ByteUtil.java b/firenio-core/src/main/java/com/firenio/common/ByteUtil.java
index 767c44d61..413b665f5 100644
--- a/firenio-core/src/main/java/com/firenio/common/ByteUtil.java
+++ b/firenio-core/src/main/java/com/firenio/common/ByteUtil.java
@@ -21,22 +21,18 @@
 
 public class ByteUtil {
 
-    private static final String[] HEXS      = new String[256];
-    private static final String[] NUMS      = new String[256];
-    private static final byte[]   CHAR_NUMS = new byte[10];
+    private static final String[] HEXES = new String[256];
+    private static final String[] NUMS  = new String[256];
 
     static {
         for (int i = 0; i < 16; i++) {
-            HEXS[i] = "0" + Integer.toHexString(i);
+            HEXES[i] = "0" + Integer.toHexString(i);
             NUMS[i] = String.valueOf(i);
         }
-        for (int i = 16; i < HEXS.length; i++) {
-            HEXS[i] = Integer.toHexString(i);
+        for (int i = 16; i < HEXES.length; i++) {
+            HEXES[i] = Integer.toHexString(i);
             NUMS[i] = String.valueOf(i);
         }
-        for (int i = 0; i < CHAR_NUMS.length; i++) {
-            CHAR_NUMS[i] = (byte) NUMS[i].charAt(0);
-        }
     }
 
     private static void checkLength(byte[] bytes, int length, int offset) {
@@ -81,15 +77,10 @@ public static boolean equalsArray(byte[] bs1, int off1, byte[] bs2, int off2, in
         return true;
     }
 
-    public static int findNextPositivePowerOfTwo(final int value) {
-        assert value > Integer.MIN_VALUE && value < 0x40000000;
-        return 1 << (32 - Integer.numberOfLeadingZeros(value - 1));
-    }
-
     /**
      * 右起0 ~ 7
      */
-    public static boolean getBoolean(byte b, int pos) {
+    public static boolean getBit(byte b, int pos) {
         return ((b >>> pos) & 1) != 0;
     }
 
@@ -114,7 +105,7 @@ public static byte[] getBytesFromHexString(String data) {
     }
 
     public static String getHexString(byte b) {
-        return HEXS[b & 0xFF];
+        return HEXES[b & 0xFF];
     }
 
     public static String getHexString(byte[] array) {
@@ -174,14 +165,11 @@ public static int getInt(long address) {
     }
 
     public static int getInt31(byte[] bytes, int offset) {
-        return getInt(bytes, offset) & 0x7fffffff;
+        return getInt31(getInt(bytes, offset));
     }
 
     public static int getInt31(int value) {
-        if (value < 0) {
-            return value & 0x7FFFFFFF;
-        }
-        return value;
+        return value & 0x7FFFFFFF;
     }
 
     public static int getIntLE(byte[] bytes, int offset) {
@@ -190,9 +178,9 @@ public static int getIntLE(byte[] bytes, int offset) {
 
     public static int getIntLE(long address) {
         if (Unsafe.isLittleOrder()) {
-            return Unsafe.getShort(address);
+            return Unsafe.getInt(address);
         } else {
-            return Integer.reverseBytes(Unsafe.getShort(address));
+            return Integer.reverseBytes(Unsafe.getInt(address));
         }
     }
 
@@ -233,10 +221,6 @@ public static String getNumString(byte b) {
         return NUMS[b & 0xFF];
     }
 
-    public static byte getNumCharByte(int value) {
-        return CHAR_NUMS[value];
-    }
-
     public static short getShort(byte[] bytes, int offset) {
         checkLength(bytes, 2, offset);
         int v1 = ((bytes[offset + 0] & 0xff) << 8 * 1);
@@ -396,14 +380,10 @@ public static void putShortLE(long address, short value) {
         }
     }
 
-    public static int safeFindNextPositivePowerOfTwo(final int value) {
-        return value <= 0 ? 1 : value >= 0x40000000 ? 0x40000000 : findNextPositivePowerOfTwo(value);
-    }
-
     public static int skip(ByteBuf src, int p, int e, byte v) {
         int i = p;
         for (; i < e; i++) {
-            if (src.absByte(i) != v) {
+            if (src.getByteAbs(i) != v) {
                 return i;
             }
         }
diff --git a/firenio-core/src/main/java/com/firenio/common/Cryptos.java b/firenio-core/src/main/java/com/firenio/common/Cryptos.java
index 5082e10f7..ad522d0ce 100644
--- a/firenio-core/src/main/java/com/firenio/common/Cryptos.java
+++ b/firenio-core/src/main/java/com/firenio/common/Cryptos.java
@@ -100,7 +100,7 @@ public static String aes_de(String content, String password, Charset charset) th
     public static byte[] aes_en(byte[] content, byte[] password) throws Exception {
         KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
         // 利用用户密码作为随机数初始化出,128位的key生产者
-        //加密没关系,SecureRandom是生成安全随机数序列,password.getBytes()是种子,只要种子相同,序列就一样,所以解密只要有password就行
+        //加密没关系,SecureRandom是生成安全随机数序列,password.readBytes()是种子,只要种子相同,序列就一样,所以解密只要有password就行
         SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
         random.setSeed(password);
         kgen.init(128, random);
diff --git a/firenio-core/src/main/java/com/firenio/common/FileUtil.java b/firenio-core/src/main/java/com/firenio/common/FileUtil.java
index ff119f401..defa62a6d 100644
--- a/firenio-core/src/main/java/com/firenio/common/FileUtil.java
+++ b/firenio-core/src/main/java/com/firenio/common/FileUtil.java
@@ -483,11 +483,11 @@ public static long skip(InputStream input, long toSkip) throws IOException {
 
     public static void skipFully(InputStream input, long toSkip) throws IOException {
         if (toSkip < 0L) {
-            throw new IllegalArgumentException("Bytes to skip must not be negative: " + toSkip);
+            throw new IllegalArgumentException("Bytes to skipRead must not be negative: " + toSkip);
         }
         long skipped = skip(input, toSkip);
         if (skipped != toSkip) {
-            throw new EOFException("Bytes to skip: " + toSkip + " actual: " + skipped);
+            throw new EOFException("Bytes to skipRead: " + toSkip + " actual: " + skipped);
         }
     }
 
diff --git a/firenio-core/src/main/java/com/firenio/common/Properties.java b/firenio-core/src/main/java/com/firenio/common/Properties.java
index f4c2d32b1..8cdd7664c 100644
--- a/firenio-core/src/main/java/com/firenio/common/Properties.java
+++ b/firenio-core/src/main/java/com/firenio/common/Properties.java
@@ -38,7 +38,7 @@ public boolean getBooleanProperty(String key, boolean defaultValue) {
         if (Util.isNullOrBlank(temp)) {
             return defaultValue;
         }
-        return Boolean.valueOf(temp);
+        return Boolean.parseBoolean(temp);
     }
 
     public double getDoubleProperty(String key) {
@@ -50,7 +50,7 @@ public double getDoubleProperty(String key, double defaultValue) {
         if (Util.isNullOrBlank(temp)) {
             return defaultValue;
         }
-        return Double.valueOf(temp);
+        return Double.parseDouble(temp);
     }
 
     public int getIntegerProperty(String key) {
@@ -77,14 +77,6 @@ public long getLongProperty(String key, long defaultValue) {
         return Long.parseLong(temp);
     }
 
-    public String getPropertyNoBlank(String key) throws PropertiesException {
-        String value = getProperty(key);
-        if (Util.isNullOrBlank(value)) {
-            throw new PropertiesException("property " + key + " is empty");
-        }
-        return value;
-    }
-
     private void insertOneRow(String line) {
         if (Util.isNullOrBlank(line)) {
             return;
@@ -115,19 +107,4 @@ private String trim(String value) {
         return value.trim().replace("\r", "").replace("\t", "");
     }
 
-    class PropertiesException extends Exception {
-
-        private static final long serialVersionUID = 1L;
-
-        public PropertiesException() {}
-
-        public PropertiesException(String message) {
-            super(message);
-        }
-
-        public PropertiesException(String message, Throwable cause) {
-            super(message, cause);
-        }
-    }
-
 }
diff --git a/firenio-core/src/main/java/com/firenio/common/Unsafe.java b/firenio-core/src/main/java/com/firenio/common/Unsafe.java
index 35aec2224..69efa49ba 100644
--- a/firenio-core/src/main/java/com/firenio/common/Unsafe.java
+++ b/firenio-core/src/main/java/com/firenio/common/Unsafe.java
@@ -24,6 +24,8 @@
 import java.security.PrivilegedAction;
 import java.security.PrivilegedExceptionAction;
 
+import com.firenio.Options;
+
 
 /**
  * @author wangkai
@@ -33,32 +35,53 @@ public class Unsafe {
 
     public static final  long           ARRAY_BASE_OFFSET;
     public static final  long           BUFFER_ADDRESS_OFFSET;
+    public static final  boolean        IS_LINUX              = isLinux();
+    public static final  boolean        IS_ANDROID            = isAndroid();
+    public static final  boolean        UNSAFE_AVAILABLE      = isUnsafeAvailable();
+    public static final  boolean        UNSAFE_BUF_AVAILABLE;
+    public static final  boolean        DIRECT_BUFFER_AVAILABLE;
     // This number limits the number of bytes to copy per call to Unsafe's
-    // copyMemory method. A limit is imposed to allow for safe point polling
+    // copyMemory method. A writeIndex is imposed to allow for safe point polling
     // during a large copy
     private static final long           UNSAFE_COPY_THRESHOLD = 1024L * 1024L;
-    private static final ByteOrder      nativeByteOrder;
+    private static final ByteOrder      nativeByteOrder       = ByteOrder.nativeOrder();
+    private static final boolean        RAW_DIRECT_AVAILABLE;
     private static final InternalUnsafe UNSAFE;
     private static final int            JAVA_VERSION          = majorJavaVersion();
     private static final Constructor DIRECT_BUFFER_CONSTRUCTOR;
 
+
     //jdk.internal.misc.Unsafe
     //jdk.internal.ref.Cleaner
 
     static {
         UNSAFE = getUnsafe();
-        BUFFER_ADDRESS_OFFSET = fieldOffset(Util.getDeclaredField(Buffer.class, "address"));
-        ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset(byte[].class);
-        nativeByteOrder = detectByteOrder();
-        DIRECT_BUFFER_CONSTRUCTOR = getDirectBufferConstructor();
+        if (UNSAFE_AVAILABLE) {
+            UNSAFE_BUF_AVAILABLE = Options.isEnableUnsafeBuf();
+            BUFFER_ADDRESS_OFFSET = fieldOffset(Util.getDeclaredField(Buffer.class, "address"));
+            DIRECT_BUFFER_AVAILABLE = BUFFER_ADDRESS_OFFSET != -1;
+            ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset(byte[].class);
+            DIRECT_BUFFER_CONSTRUCTOR = getDirectBufferConstructor();
+            RAW_DIRECT_AVAILABLE = DIRECT_BUFFER_CONSTRUCTOR != null;
+        } else {
+            if (Options.isEnableUnsafeBuf()) {
+                throw new Error("UnsafeBuf enabled but no unsafe available");
+            }
+            UNSAFE_BUF_AVAILABLE = false;
+            BUFFER_ADDRESS_OFFSET = -1;
+            DIRECT_BUFFER_AVAILABLE = false;
+            ARRAY_BASE_OFFSET = -1;
+            DIRECT_BUFFER_CONSTRUCTOR = null;
+            RAW_DIRECT_AVAILABLE = false;
+        }
     }
 
     private Unsafe() {}
 
     private static Constructor getDirectBufferConstructor() {
-        Constructor directBufferConstructor;
-        final ByteBuffer     direct  = ByteBuffer.allocateDirect(1);
-        long           address = -1;
+        Constructor   directBufferConstructor = null;
+        final ByteBuffer direct                  = ByteBuffer.allocateDirect(1);
+        long             address                 = -1;
         try {
             final Object res = AccessController.doPrivileged(new PrivilegedAction() {
                 @Override
@@ -70,7 +93,7 @@ public Object run() {
                             return cause;
                         }
                         return constructor;
-                    } catch (Exception e) {
+                    } catch (Throwable e) {
                         return e;
                     }
                 }
@@ -80,29 +103,43 @@ public Object run() {
                 try {
                     ((Constructor) res).newInstance(address, 1);
                     directBufferConstructor = (Constructor) res;
-                } catch (Exception e) {
-                    throw new Error("get DirectBuffer Constructor failed", e);
+                } catch (Throwable e) {
+                    return null;
                 }
             } else {
-                throw new Error("get DirectBuffer Constructor failed", (Throwable) res);
+                return null;
             }
         } finally {
             if (address != -1) {
                 free(address);
             }
-            free(address(direct));
         }
         return directBufferConstructor;
     }
 
+    private static boolean isAndroid() {
+        return "Dalvik".equalsIgnoreCase(System.getProperty("java.vm.name"));
+    }
+
+    private static boolean isLinux() {
+        return Util.getStringProperty("os.name", "").toLowerCase().startsWith("lin");
+    }
+
+    private static boolean isUnsafeAvailable() {
+        return !IS_ANDROID && Options.isEnableUnsafe();
+    }
 
     private static InternalUnsafe getUnsafe() {
-        //        if (javaVersion() > 8) {
-        //            return new Jdk8UpUnsafe();
-        //        } else {
-        //            return new Jdk8AndLowUnsafe();
-        //        }
-        return new Jdk8AndLowUnsafe();
+        if (UNSAFE_AVAILABLE) {
+            //        if (javaVersion() > 8) {
+            //            return new Jdk8UpUnsafe();
+            //        } else {
+            //            return new Jdk8AndLowUnsafe();
+            //        }
+            return new Jdk8AndLowUnsafe();
+        } else {
+            return new NoUnsafe();
+        }
     }
 
     public static long address(ByteBuffer buffer) {
@@ -152,12 +189,12 @@ public static void copyFromArray(byte[] src, long srcPos, long dstAddr, long len
         }
     }
 
-    public static void copyFromArray(ByteBuffer buf, long dstAddr, long length) {
-        copyFromArray(buf.array(), buf.position(), dstAddr, length);
-    }
-
     public static void copyMemory(ByteBuffer buf, long targetAddress, long length) {
-        UNSAFE.copyMemory(address(buf) + buf.position(), targetAddress, length);
+        if (buf.isDirect()) {
+            UNSAFE.copyMemory(address(buf) + buf.position(), targetAddress, length);
+        } else {
+            copyFromArray(buf.array(), buf.position(), targetAddress, length);
+        }
     }
 
     public static void copyMemory(long srcAddress, long targetAddress, long length) {
@@ -176,7 +213,7 @@ public static void copyMemory(Object src, long srcOffset, Object target, long ta
      * @param dstPos  offset within destination array of the first element to write
      * @param length  number of bytes to copy
      */
-    public static void copyToArray(long srcAddr, Object dst, long dstPos, long length) {
+    public static void copyToArray(long srcAddr, byte[] dst, long dstPos, long length) {
         long offset = ARRAY_BASE_OFFSET + dstPos;
         while (length > 0) {
             long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
@@ -187,24 +224,6 @@ public static void copyToArray(long srcAddr, Object dst, long dstPos, long lengt
         }
     }
 
-    private static ByteOrder detectByteOrder() {
-        long a = UNSAFE.allocateMemory(8);
-        try {
-            UNSAFE.putLong(a, 0x0102030405060708L);
-            byte b = UNSAFE.getByte(a);
-            switch (b) {
-                case 0x01:
-                    return ByteOrder.BIG_ENDIAN;
-                case 0x08:
-                    return ByteOrder.LITTLE_ENDIAN;
-                default:
-                    throw new Error("detect byte order failed");
-            }
-        } finally {
-            UNSAFE.freeMemory(a);
-        }
-    }
-
     private static long fieldOffset(Field field) {
         return field == null || UNSAFE == null ? -1 : UNSAFE.objectFieldOffset(field);
     }
@@ -338,38 +357,45 @@ public static int javaVersion() {
     }
 
     public static ByteBuffer allocateDirectByteBuffer(int cap) {
-        long address = allocate(cap);
-        if (address == -1) {
-            throw new RuntimeException("no enough space(direct): " + cap);
-        }
-        try {
-            return (ByteBuffer) DIRECT_BUFFER_CONSTRUCTOR.newInstance(address, cap);
-        } catch (Throwable e) {
-            free(address);
-            throw new Error(e);
+        if (RAW_DIRECT_AVAILABLE) {
+            long address = allocate(cap);
+            if (address == -1) {
+                throw new RuntimeException("no enough space(direct): " + cap);
+            }
+            try {
+                return (ByteBuffer) DIRECT_BUFFER_CONSTRUCTOR.newInstance(address, cap);
+            } catch (Throwable e) {
+                free(address);
+                throw new Error(e);
+            }
+        } else {
+            return ByteBuffer.allocateDirect(cap);
         }
     }
 
     public static void freeByteBuffer(ByteBuffer buffer) {
         if (buffer.isDirect()) {
-            //            boolean free = false;
-            //            if (javaVersion() > 8) {
-            //                sun.nio.ch.DirectBuffer  b = (sun.nio.ch.DirectBuffer) buffer;
-            //                jdk.internal.ref.Cleaner c = b.cleaner();
-            //                if (c != null) {
-            //                    c.clean();
-            //                    free = true;
-            //                }
-            //            } else {
-            //                if (((sun.nio.ch.DirectBuffer) buffer).cleaner() != null) {
-            //                    ((sun.nio.ch.DirectBuffer) buffer).cleaner().clean();
-            //                    free = true;
-            //                }
-            //            }
-            //            if (!free) {
-            //                free(address(buffer));
-            //            }
-            free(address(buffer));
+            if (RAW_DIRECT_AVAILABLE) {
+                free(address(buffer));
+            } else {
+                boolean free = false;
+                //            if (javaVersion() > 8) {
+                //                sun.nio.ch.DirectBuffer  b = (sun.nio.ch.DirectBuffer) buffer;
+                //                jdk.internal.ref.Cleaner c = b.cleaner();
+                //                if (c != null) {
+                //                    c.clean();
+                //                    free = true;
+                //                }
+                //            } else {
+                if (((sun.nio.ch.DirectBuffer) buffer).cleaner() != null) {
+                    ((sun.nio.ch.DirectBuffer) buffer).cleaner().clean();
+                    free = true;
+                }
+                //            }
+                if (!free) {
+                    free(address(buffer));
+                }
+            }
         }
     }
 
@@ -404,8 +430,6 @@ interface InternalUnsafe {
 
         long fieldOffset(Field field);
 
-        void free(long address);
-
         boolean getBoolean(Object target, long offset);
 
         byte getByte(long address);
@@ -467,7 +491,7 @@ interface InternalUnsafe {
         void freeMemory(long address);
     }
 
-    //    static class Jdk8UpUnsafe implements InternalUnsafe {
+    //    static final class Jdk8UpUnsafe implements InternalUnsafe {
     //
     //        private jdk.internal.misc.Unsafe UNSAFE;
     //
@@ -488,7 +512,7 @@ interface InternalUnsafe {
     //        }
     //
     //        public void copyMemory(ByteBuffer buf, long targetAddress, long length) {
-    //            UNSAFE.copyMemory(address(buf) + buf.position(), targetAddress, length);
+    //            UNSAFE.copyMemory(address(buf) + buf.readIndex(), targetAddress, length);
     //        }
     //
     //        public void copyMemory(long srcAddress, long targetAddress, long length) {
@@ -511,48 +535,48 @@ interface InternalUnsafe {
     //            return UNSAFE.getBoolean(target, offset);
     //        }
     //
-    //        public byte getByte(long address) {
-    //            return UNSAFE.getByte(address);
+    //        public byte readByte(long address) {
+    //            return UNSAFE.readByte(address);
     //        }
     //
-    //        public byte getByte(Object target, long offset) {
-    //            return UNSAFE.getByte(target, offset);
+    //        public byte readByte(Object target, long offset) {
+    //            return UNSAFE.readByte(target, offset);
     //        }
     //
-    //        public double getDouble(Object target, long offset) {
-    //            return UNSAFE.getDouble(target, offset);
+    //        public double readDouble(Object target, long offset) {
+    //            return UNSAFE.readDouble(target, offset);
     //        }
     //
-    //        public float getFloat(Object target, long offset) {
-    //            return UNSAFE.getFloat(target, offset);
+    //        public float readFloat(Object target, long offset) {
+    //            return UNSAFE.readFloat(target, offset);
     //        }
     //
-    //        public int getInt(long address) {
-    //            return UNSAFE.getInt(address);
+    //        public int readInt(long address) {
+    //            return UNSAFE.readInt(address);
     //        }
     //
-    //        public int getInt(Object target, long offset) {
-    //            return UNSAFE.getInt(target, offset);
+    //        public int readInt(Object target, long offset) {
+    //            return UNSAFE.readInt(target, offset);
     //        }
     //
-    //        public long getLong(long address) {
-    //            return UNSAFE.getLong(address);
+    //        public long readLong(long address) {
+    //            return UNSAFE.readLong(address);
     //        }
     //
-    //        public long getLong(Object target, long offset) {
-    //            return UNSAFE.getLong(target, offset);
+    //        public long readLong(Object target, long offset) {
+    //            return UNSAFE.readLong(target, offset);
     //        }
     //
     //        public Object getObject(Object target, long offset) {
     //            return UNSAFE.getObject(target, offset);
     //        }
     //
-    //        public short getShort(long address) {
-    //            return UNSAFE.getShort(address);
+    //        public short readShort(long address) {
+    //            return UNSAFE.readShort(address);
     //        }
     //
-    //        public short getShort(Object target, long offset) {
-    //            return UNSAFE.getShort(target, offset);
+    //        public short readShort(Object target, long offset) {
+    //            return UNSAFE.readShort(target, offset);
     //        }
     //
     //        public long objectFieldOffset(Field field) {
@@ -563,48 +587,48 @@ interface InternalUnsafe {
     //            UNSAFE.putBoolean(target, offset, value);
     //        }
     //
-    //        public void putByte(long address, byte value) {
-    //            UNSAFE.putByte(address, value);
+    //        public void writeByte(long address, byte value) {
+    //            UNSAFE.writeByte(address, value);
     //        }
     //
-    //        public void putByte(Object target, long offset, byte value) {
-    //            UNSAFE.putByte(target, offset, value);
+    //        public void writeByte(Object target, long offset, byte value) {
+    //            UNSAFE.writeByte(target, offset, value);
     //        }
     //
-    //        public void putDouble(Object target, long offset, double value) {
-    //            UNSAFE.putDouble(target, offset, value);
+    //        public void setDouble(Object target, long offset, double value) {
+    //            UNSAFE.setDouble(target, offset, value);
     //        }
     //
-    //        public void putFloat(Object target, long offset, float value) {
-    //            UNSAFE.putFloat(target, offset, value);
+    //        public void setFloat(Object target, long offset, float value) {
+    //            UNSAFE.setFloat(target, offset, value);
     //        }
     //
-    //        public void putInt(long address, int value) {
-    //            UNSAFE.putInt(address, value);
+    //        public void writeInt(long address, int value) {
+    //            UNSAFE.writeInt(address, value);
     //        }
     //
-    //        public void putInt(Object target, long offset, int value) {
-    //            UNSAFE.putInt(target, offset, value);
+    //        public void writeInt(Object target, long offset, int value) {
+    //            UNSAFE.writeInt(target, offset, value);
     //        }
     //
-    //        public void putLong(long address, long value) {
-    //            UNSAFE.putLong(address, value);
+    //        public void setLong(long address, long value) {
+    //            UNSAFE.setLong(address, value);
     //        }
     //
-    //        public void putLong(Object target, long offset, long value) {
-    //            UNSAFE.putLong(target, offset, value);
+    //        public void setLong(Object target, long offset, long value) {
+    //            UNSAFE.setLong(target, offset, value);
     //        }
     //
     //        public void putObject(Object target, long offset, Object value) {
     //            UNSAFE.putObject(target, offset, value);
     //        }
     //
-    //        public void putShort(long address, short value) {
-    //            UNSAFE.putShort(address, value);
+    //        public void writeShort(long address, short value) {
+    //            UNSAFE.writeShort(address, value);
     //        }
     //
-    //        public void putShort(Object target, long offset, short value) {
-    //            UNSAFE.putShort(target, offset, value);
+    //        public void writeShort(Object target, long offset, short value) {
+    //            UNSAFE.writeShort(target, offset, value);
     //        }
     //
     //        public void setMemory(long address, long numBytes, byte value) {
@@ -658,7 +682,7 @@ interface InternalUnsafe {
     //    }
 
 
-    static class Jdk8AndLowUnsafe implements InternalUnsafe {
+    static final class Jdk8AndLowUnsafe implements InternalUnsafe {
 
         private sun.misc.Unsafe UNSAFE;
 
@@ -666,138 +690,167 @@ static class Jdk8AndLowUnsafe implements InternalUnsafe {
             UNSAFE = getUnsafe();
         }
 
+        @Override
         public boolean compareAndSwapInt(Object o, long offset, int expected, int val) {
             return UNSAFE.compareAndSwapInt(o, offset, expected, val);
         }
 
+        @Override
         public boolean compareAndSwapLong(Object o, long offset, int expected, long val) {
             return UNSAFE.compareAndSwapLong(o, offset, expected, val);
         }
 
+        @Override
         public boolean compareAndSwapObject(Object o, long offset, Object expected, Object val) {
             return UNSAFE.compareAndSwapObject(o, offset, expected, val);
         }
 
+        @Override
         public void copyMemory(ByteBuffer buf, long targetAddress, long length) {
             UNSAFE.copyMemory(address(buf) + buf.position(), targetAddress, length);
         }
 
+        @Override
         public void copyMemory(long srcAddress, long targetAddress, long length) {
             UNSAFE.copyMemory(srcAddress, targetAddress, length);
         }
 
+        @Override
         public void copyMemory(Object src, long srcOffset, Object target, long targetOffset, long length) {
             UNSAFE.copyMemory(src, srcOffset, target, targetOffset, length);
         }
 
+        @Override
         public long fieldOffset(Field field) {
             return UNSAFE.objectFieldOffset(field);
         }
 
-        public void free(long address) {
-            UNSAFE.freeMemory(address);
-        }
-
+        @Override
         public boolean getBoolean(Object target, long offset) {
             return UNSAFE.getBoolean(target, offset);
         }
 
+        @Override
         public byte getByte(long address) {
             return UNSAFE.getByte(address);
         }
 
+        @Override
         public byte getByte(Object target, long offset) {
             return UNSAFE.getByte(target, offset);
         }
 
+        @Override
         public double getDouble(Object target, long offset) {
             return UNSAFE.getDouble(target, offset);
         }
 
+        @Override
         public float getFloat(Object target, long offset) {
             return UNSAFE.getFloat(target, offset);
         }
 
+        @Override
         public int getInt(long address) {
             return UNSAFE.getInt(address);
         }
 
+        @Override
         public int getInt(Object target, long offset) {
             return UNSAFE.getInt(target, offset);
         }
 
+        @Override
         public long getLong(long address) {
             return UNSAFE.getLong(address);
         }
 
+        @Override
         public long getLong(Object target, long offset) {
             return UNSAFE.getLong(target, offset);
         }
 
+        @Override
         public Object getObject(Object target, long offset) {
             return UNSAFE.getObject(target, offset);
         }
 
+        @Override
         public short getShort(long address) {
             return UNSAFE.getShort(address);
         }
 
+        @Override
         public short getShort(Object target, long offset) {
             return UNSAFE.getShort(target, offset);
         }
 
+        @Override
         public long objectFieldOffset(Field field) {
             return UNSAFE.objectFieldOffset(field);
         }
 
+        @Override
         public void putBoolean(Object target, long offset, boolean value) {
             UNSAFE.putBoolean(target, offset, value);
         }
 
+        @Override
         public void putByte(long address, byte value) {
             UNSAFE.putByte(address, value);
         }
 
+        @Override
         public void putByte(Object target, long offset, byte value) {
             UNSAFE.putByte(target, offset, value);
         }
 
+        @Override
         public void putDouble(Object target, long offset, double value) {
             UNSAFE.putDouble(target, offset, value);
         }
 
+        @Override
         public void putFloat(Object target, long offset, float value) {
             UNSAFE.putFloat(target, offset, value);
         }
 
+        @Override
         public void putInt(long address, int value) {
             UNSAFE.putInt(address, value);
         }
 
+        @Override
         public void putInt(Object target, long offset, int value) {
             UNSAFE.putInt(target, offset, value);
         }
 
+        @Override
         public void putLong(long address, long value) {
             UNSAFE.putLong(address, value);
         }
 
+        @Override
         public void putLong(Object target, long offset, long value) {
             UNSAFE.putLong(target, offset, value);
         }
 
+        @Override
         public void putObject(Object target, long offset, Object value) {
             UNSAFE.putObject(target, offset, value);
         }
 
+        @Override
         public void putShort(long address, short value) {
             UNSAFE.putShort(address, value);
         }
 
+        @Override
         public void putShort(Object target, long offset, short value) {
             UNSAFE.putShort(target, offset, value);
         }
 
+        @Override
         public void setMemory(long address, long numBytes, byte value) {
             UNSAFE.setMemory(address, numBytes, value);
         }
@@ -849,5 +902,156 @@ public sun.misc.Unsafe run() throws Exception {
 
     }
 
+    static final class NoUnsafe implements InternalUnsafe {
+
+        public boolean compareAndSwapInt(Object o, long offset, int expected, int val) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public boolean compareAndSwapLong(Object o, long offset, int expected, long val) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public boolean compareAndSwapObject(Object o, long offset, Object expected, Object val) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void copyMemory(ByteBuffer buf, long targetAddress, long length) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void copyMemory(long srcAddress, long targetAddress, long length) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void copyMemory(Object src, long srcOffset, Object target, long targetOffset, long length) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public long fieldOffset(Field field) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public boolean getBoolean(Object target, long offset) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public byte getByte(long address) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public byte getByte(Object target, long offset) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public double getDouble(Object target, long offset) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public float getFloat(Object target, long offset) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public int getInt(long address) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public int getInt(Object target, long offset) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public long getLong(long address) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public long getLong(Object target, long offset) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public Object getObject(Object target, long offset) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public short getShort(long address) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public short getShort(Object target, long offset) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public long objectFieldOffset(Field field) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void putBoolean(Object target, long offset, boolean value) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void putByte(long address, byte value) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void putByte(Object target, long offset, byte value) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void putDouble(Object target, long offset, double value) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void putFloat(Object target, long offset, float value) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void putInt(long address, int value) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void putInt(Object target, long offset, int value) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void putLong(long address, long value) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void putLong(Object target, long offset, long value) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void putObject(Object target, long offset, Object value) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void putShort(long address, short value) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void putShort(Object target, long offset, short value) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void setMemory(long address, long numBytes, byte value) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public long arrayBaseOffset(Class clazz) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public long allocateMemory(long length) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public Object allocateInstance(Class clazz) throws InstantiationException {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+
+        public void freeMemory(long address) {
+            throw new UnsupportedOperationException("unsafe not available");
+        }
+    }
+
 
 }
diff --git a/firenio-core/src/main/java/com/firenio/common/Util.java b/firenio-core/src/main/java/com/firenio/common/Util.java
index 7fe9385e4..556a5f856 100644
--- a/firenio-core/src/main/java/com/firenio/common/Util.java
+++ b/firenio-core/src/main/java/com/firenio/common/Util.java
@@ -15,13 +15,12 @@
  */
 package com.firenio.common;
 
-import java.io.Closeable;
 import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Field;
 import java.nio.channels.Selector;
 import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -40,9 +39,9 @@
  */
 public class Util {
 
-    public static final  Charset  ASCII       = Charset.forName("ASCII");
+    public static final  Charset  ASCII       = StandardCharsets.US_ASCII;
     public static final  Charset  GBK         = Charset.forName("GBK");
-    public static final  Charset  UTF8        = Charset.forName("UTF-8");
+    public static final  Charset  UTF8        = StandardCharsets.UTF_8;
     private static final Logger   logger      = LoggerFactory.getLogger(Util.class);
     private static final String[] int_strings = new String[2048];
 
@@ -52,34 +51,24 @@ public class Util {
         }
     }
 
-    @SuppressWarnings("rawtypes")
-    public static List array2List(Object[] array) {
-        if (array == null || array.length == 0) {
-            return null;
-        }
-        return new ArrayList<>(Arrays.asList(array));
-    }
-
     public static int availableProcessors() {
         return Runtime.getRuntime().availableProcessors();
     }
 
     public static void close(AutoCloseable closeable) {
-        if (closeable == null) {
-            return;
-        }
-        try {
-            closeable.close();
-        } catch (Exception e) {
-            logger.warn(e.getMessage(), e);
+        if (closeable != null) {
+            try {
+                closeable.close();
+            } catch (Throwable e) {
+                logger.warn(e.getMessage(), e);
+            }
         }
     }
 
-    public static void clear(Collection coll) {
-        if (coll == null) {
-            return;
+    public static void clear(Collection collection) {
+        if (collection != null) {
+            collection.clear();
         }
-        coll.clear();
     }
 
     public static void clear(IntMap map) {
@@ -89,20 +78,8 @@ public static void clear(IntMap map) {
     }
 
     public static void clear(Map map) {
-        if (map == null) {
-            return;
-        }
-        map.clear();
-    }
-
-    public static void close(Closeable closeable) {
-        if (closeable == null) {
-            return;
-        }
-        try {
-            closeable.close();
-        } catch (Exception e) {
-            logger.warn(e.getMessage(), e);
+        if (map != null) {
+            map.clear();
         }
     }
 
@@ -113,17 +90,6 @@ public static String int2String(int i) {
         return String.valueOf(i);
     }
 
-    public static void close(Selector selector) {
-        if (selector == null) {
-            return;
-        }
-        try {
-            selector.close();
-        } catch (Exception e) {
-            logger.warn(e.getMessage(), e);
-        }
-    }
-
     public static Thread exec(Runnable runnable, String name) {
         return exec(runnable, name, false);
     }
@@ -142,25 +108,6 @@ public static Thread exec(Runnable runnable, String name, boolean daemon) {
         return t;
     }
 
-    public static Class forName(String className) {
-        try {
-            return Class.forName(className);
-        } catch (ClassNotFoundException e) {
-            return null;
-        }
-    }
-
-    public static Class forName(String className, Class defaultClass) {
-        if (isNullOrBlank(className)) {
-            return defaultClass;
-        }
-        try {
-            return Class.forName(className);
-        } catch (ClassNotFoundException e) {
-            return defaultClass;
-        }
-    }
-
     public static boolean getBooleanProperty(String key) {
         return getBooleanProperty(key, false);
     }
@@ -170,7 +117,7 @@ public static boolean getBooleanProperty(String key, boolean defaultValue) {
         if (!isNullOrBlank(v)) {
             try {
                 return isTrueValue(v);
-            } catch (Exception e) {
+            } catch (Throwable e) {
             }
         }
         return defaultValue;
@@ -213,7 +160,7 @@ public static int getIntProperty(String key, int defaultValue) {
         if (!isNullOrBlank(v)) {
             try {
                 return Integer.parseInt(v);
-            } catch (Exception e) {
+            } catch (Throwable e) {
             }
         }
         return defaultValue;
@@ -260,7 +207,7 @@ public static Object getValueOfLast(Object target, String fieldName) {
                 }
                 c = next;
             }
-        } catch (Exception e) {
+        } catch (Throwable e) {
             throw new RuntimeException(e);
         }
     }
@@ -336,7 +283,7 @@ public static Object newInstance(Class clazz) {
         }
         try {
             return clazz.newInstance();
-        } catch (Exception e) {
+        } catch (Throwable e) {
             throw new RuntimeException(e);
         }
     }
@@ -353,12 +300,22 @@ public static long past(long start) {
         return now_f() - start;
     }
 
-    public static void printArray(int[] array) {
-        for (int i = 0; i < array.length; i++) {
-            System.out.print(array[i]);
-            System.out.print(",");
+    public static String arrayToString(int[] array) {
+        return arrayToString(array, 0, array.length);
+    }
+
+    public static String arrayToString(int[] array, int off, int len) {
+        if (len == 0) {
+            return "";
         }
-        System.out.println();
+        StringBuilder sb  = new StringBuilder();
+        int           end = off + len;
+        for (int i = off; i < end; i++) {
+            sb.append(array[i]);
+            sb.append(',');
+        }
+        sb.setLength(sb.length() - 1);
+        return sb.toString();
     }
 
     public static void printArray(Object[] array) {
@@ -419,7 +376,7 @@ public static void setObjectValue(Object target, Object value, String fieldName)
             }
             trySetAccessible(field);
             field.set(target, value);
-        } catch (Exception e) {
+        } catch (Throwable e) {
             throw new RuntimeException(e);
         }
     }
@@ -521,20 +478,6 @@ public static void stop(LifeCycle lifeCycle) {
         }
     }
 
-    public static void testUuid() {
-
-        int    count = 1024 * 1024;
-        long   start = now();
-        String str   = null;
-        for (int i = 0; i < count; i++) {
-            str = randomUUID();
-            //            str = UUID.randomUUID().toString();
-        }
-        System.out.println(str);
-        System.out.println(past(start));
-
-    }
-
     public static List toList(int initialListSize, String... protocols) {
         if (protocols == null) {
             return null;
@@ -560,19 +503,18 @@ public static Throwable trySetAccessible(AccessibleObject object) {
         try {
             object.setAccessible(true);
             return null;
-        } catch (Exception e) {
+        } catch (Throwable e) {
             return e;
         }
     }
 
     public static void unbind(ChannelAcceptor unbindable) {
-        if (unbindable == null) {
-            return;
-        }
-        try {
-            unbindable.unbind();
-        } catch (Exception e) {
-            logger.warn(e.getMessage(), e);
+        if (unbindable != null) {
+            try {
+                unbindable.unbind();
+            } catch (Throwable e) {
+                logger.warn(e.getMessage(), e);
+            }
         }
     }
 
@@ -584,7 +526,7 @@ public static  T unknownStackTrace(T cause, Class clazz,
     public static int valueOf(int value, byte[] data) {
         int v = value;
         for (int i = data.length - 1; i > -1; i--) {
-            data[i] = ByteUtil.getNumCharByte(v % 10);
+            data[i] = (byte) ((v % 10) + ((byte) '0'));
             v = v / 10;
             if (v == 0) {
                 return i;
diff --git a/firenio-core/src/main/java/com/firenio/component/Channel.java b/firenio-core/src/main/java/com/firenio/component/Channel.java
index 0570c2479..f709a5f9e 100644
--- a/firenio-core/src/main/java/com/firenio/component/Channel.java
+++ b/firenio-core/src/main/java/com/firenio/component/Channel.java
@@ -15,7 +15,6 @@
  */
 package com.firenio.component;
 
-import java.io.Closeable;
 import java.io.IOException;
 import java.lang.reflect.Field;
 import java.net.InetSocketAddress;
@@ -39,6 +38,7 @@
 import com.firenio.Releasable;
 import com.firenio.buffer.ByteBuf;
 import com.firenio.buffer.ByteBufAllocator;
+import com.firenio.collection.AttributeMap;
 import com.firenio.common.Unsafe;
 import com.firenio.common.Util;
 import com.firenio.component.NioEventLoop.EpollEventLoop;
@@ -47,19 +47,24 @@
 import com.firenio.log.Logger;
 import com.firenio.log.LoggerFactory;
 
+import static com.firenio.Develop.SSL_DEBUG;
 import static com.firenio.Develop.debugException;
 import static com.firenio.common.Util.unknownStackTrace;
 
 
 //请勿使用remote.getRemoteHost(),可能出现阻塞
-public abstract class Channel implements Runnable, Closeable {
+public abstract class Channel extends AttributeMap implements Runnable, AutoCloseable {
 
     public static final InetSocketAddress ERROR_SOCKET_ADDRESS  = new InetSocketAddress(0);
     public static final Logger            logger                = NEW_LOGGER();
     public static final SSLException      NOT_TLS               = NOT_TLS();
+    public static final IOException       CLOSED_CHANNEL        = CLOSED_CHANNEL();
+    public static final IOException       SSL_HANDSHAKE_FAILED  = SSL_HANDSHAKE_FAILED();
     public static final int               SSL_PACKET_LIMIT      = 1024 * 64;
     public static final SSLException      SSL_PACKET_OVER_LIMIT = SSL_PACKET_OVER_LIMIT();
     public static final SSLException      SSL_UNWRAP_OVER_LIMIT = SSL_UNWRAP_OVER_LIMIT();
+    public static final SSLException      SSL_UNWRAP_CLOSED     = SSL_UNWRAP_CLOSED();
+    public static final SSLException      SSL_WRAP_CLOSED       = SSL_WRAP_CLOSED();
     public static final SSLException      SSL_UNWRAP_EXCEPTION  = SSL_UNWRAP_EXCEPTION();
     public static final IOException       TASK_REJECT           = TASK_REJECT();
 
@@ -73,12 +78,12 @@ public abstract class Channel implements Runnable, Closeable {
     protected final    SSLEngine      ssl_engine;
     protected final    Queue write_bufs;
     protected final    Integer        channelId;
-    protected final    int            localPort;
+    protected final    short          localPort;
     protected final    String         remoteAddr;
-    protected final    int            remotePort;
+    protected final    short          remotePort;
     protected          Object         attachment;
     protected          ProtocolCodec  codec;
-    protected          int            current_wbs_len;
+    protected          byte           current_wbs_len;
     protected          boolean        in_event;
     protected          long           last_access;
     protected volatile boolean        open          = true;
@@ -89,8 +94,8 @@ public abstract class Channel implements Runnable, Closeable {
 
     Channel(NioEventLoop el, ChannelContext ctx, String ra, int lp, int rp, Integer id) {
         this.remoteAddr = ra;
-        this.localPort = lp;
-        this.remotePort = rp;
+        this.localPort = (short) lp;
+        this.remotePort = (short) rp;
         this.channelId = id;
         this.context = ctx;
         this.eventLoop = el;
@@ -109,6 +114,14 @@ public abstract class Channel implements Runnable, Closeable {
         }
     }
 
+    private static ClosedChannelException CLOSED_CHANNEL() {
+        return Util.unknownStackTrace(new ClosedChannelException(), Channel.class, "safe_close(...)");
+    }
+
+    private static SSLException SSL_HANDSHAKE_FAILED() {
+        return Util.unknownStackTrace(new SSLException("ssl handshake failed"), Channel.class, "ssl_handshake(...)");
+    }
+
     private static ClosedChannelException CLOSED_WHEN_FLUSH() {
         return Util.unknownStackTrace(new ClosedChannelException(), Channel.class, "flush(...)");
     }
@@ -123,15 +136,23 @@ private static Logger NEW_LOGGER() {
     }
 
     private static SSLException NOT_TLS() {
-        return Util.unknownStackTrace(new SSLException("NOT TLS"), Channel.class, "isEnoughSslUnwrap()");
+        return Util.unknownStackTrace(new SSLException("not tls"), Channel.class, "isEnoughSslUnwrap()");
     }
 
     private static SSLException SSL_PACKET_OVER_LIMIT() {
-        return Util.unknownStackTrace(new SSLException("over limit (" + SSL_PACKET_LIMIT + ")"), Channel.class, "isEnoughSslUnwrap()");
+        return Util.unknownStackTrace(new SSLException("over writeIndex (" + SSL_PACKET_LIMIT + ")"), Channel.class, "isEnoughSslUnwrap()");
+    }
+
+    private static SSLException SSL_UNWRAP_CLOSED() {
+        return unknownStackTrace(new SSLException("SSL_UNWRAP_CLOSED"), Channel.class, "unwrap()");
+    }
+
+    private static SSLException SSL_WRAP_CLOSED() {
+        return unknownStackTrace(new SSLException("SSL_WRAP_CLOSED"), Channel.class, "wrap()");
     }
 
     private static SSLException SSL_UNWRAP_OVER_LIMIT() {
-        return unknownStackTrace(new SSLException("over limit (SSL_UNWRAP_BUFFER_SIZE)"), Channel.class, "unwrap()");
+        return unknownStackTrace(new SSLException("over writeIndex (SSL_UNWRAP_BUFFER_SIZE)"), Channel.class, "unwrap()");
     }
 
     private static SSLException SSL_UNWRAP_EXCEPTION() {
@@ -142,7 +163,7 @@ private static IOException TASK_REJECT() {
         return Util.unknownStackTrace(new IOException(), Channel.class, "accept_reject(...)");
     }
 
-    private void slice_remain_plain(ByteBuf src) {
+    protected void slice_remain_plain(ByteBuf src) {
         //ensure the channel is open, otherwise the buf will never be released if the channel closed
         if (isOpen()) {
             plain_remain_buf = slice_remain(src);
@@ -156,14 +177,15 @@ private void slice_remain_ssl(ByteBuf src) {
     }
 
     private void accept(ByteBuf src) throws Exception {
+        final Channel       ch         = this;
         final ProtocolCodec codec      = getCodec();
         final IoEventHandle handle     = getIoEventHandle();
         final EventLoop     eel        = getExecutorEventLoop();
         final boolean       enable_wel = eel != null;
         for (; ; ) {
-            Frame f = codec.decode(this, src);
+            Frame f = codec.decode(ch, src);
             if (f == null) {
-                slice_remain_plain(src);
+                codec.storePlainReadRemain(ch, src);
                 break;
             }
             if (enable_wel) {
@@ -171,7 +193,7 @@ private void accept(ByteBuf src) throws Exception {
             } else {
                 accept_line(handle, f);
             }
-            if (!src.hasRemaining()) {
+            if (!src.hasReadableBytes()) {
                 break;
             }
         }
@@ -185,7 +207,7 @@ public void run() {
                 final Channel ch = Channel.this;
                 try {
                     ch.getIoEventHandle().accept(ch, f);
-                } catch (Exception e) {
+                } catch (Throwable e) {
                     ch.getIoEventHandle().exceptionCaught(ch, f, e);
                 }
             }
@@ -198,7 +220,7 @@ public void run() {
     private void accept_line(IoEventHandle handle, Frame frame) {
         try {
             handle.accept(this, frame);
-        } catch (Exception e) {
+        } catch (Throwable e) {
             exception_caught(frame, e);
         }
     }
@@ -213,7 +235,7 @@ public ByteBuf allocate() {
 
     public ByteBuf allocate(int limit) {
         int h = codec.getHeaderLength();
-        return alloc().allocate(h + limit).skip(h);
+        return alloc().allocate(h + limit).skipWrite(h);
     }
 
     private void check_write_overflow() {
@@ -241,6 +263,10 @@ public void run() {
 
     private void close_ssl() {
         if (enable_ssl) {
+            // fire channelEstablish to tell connector the reason of close
+            if (!ssl_handshake_finished) {
+                context.channelEstablish(this, SSL_HANDSHAKE_FAILED);
+            }
             //ref https://docs.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html
             // Indicate that application is done with engine
             if (SslContext.OPENSSL_AVAILABLE && OpenSslHelper.isOpensslEngineDestroyed(ssl_engine)) {
@@ -252,7 +278,7 @@ private void close_ssl() {
                     ByteBuf out = wrap(ByteBuf.empty());
                     write_bufs.offer(out);
                     write();
-                } catch (Exception e) {
+                } catch (Throwable e) {
                     debugException(logger, e);
                 }
             }
@@ -262,7 +288,7 @@ private void close_ssl() {
                     OpenSslHelper.setOpensslEngineReceivedShutdown(ssl_engine);
                 }
                 ssl_engine.closeInbound();
-            } catch (Exception e) {
+            } catch (Throwable e) {
                 debugException(logger, e);
             }
         }
@@ -272,7 +298,7 @@ public ByteBuf encode(Frame frame) throws Exception {
         return codec.encode(this, frame);
     }
 
-    private void exception_caught(Frame frame, Exception ex) {
+    private void exception_caught(Frame frame, Throwable ex) {
         try {
             getIoEventHandle().exceptionCaught(this, frame, ex);
         } catch (Throwable e) {
@@ -288,13 +314,12 @@ private void finish_handshake() {
     }
 
     private void fire_closed() {
-        eventLoop.removeChannel(channelId);
         List ls = context.getChannelEventListeners();
         for (int i = 0, count = ls.size(); i < count; i++) {
             ChannelEventListener l = ls.get(i);
             try {
                 l.channelClosed(this);
-            } catch (Exception e) {
+            } catch (Throwable e) {
                 logger.error(e.getMessage(), e);
             }
         }
@@ -307,7 +332,7 @@ protected void fire_opened() {
             ChannelEventListener l = ls.get(i);
             try {
                 l.channelOpened(this);
-            } catch (Exception e) {
+            } catch (Throwable e) {
                 logger.error(e.getMessage(), e);
                 Util.close(this);
                 return;
@@ -333,6 +358,7 @@ public Object getAttachment() {
         return attachment;
     }
 
+    // why the attachment is not volatile ? see setCodec
     public void setAttachment(Object attachment) {
         this.attachment = attachment;
     }
@@ -349,6 +375,9 @@ public ProtocolCodec getCodec() {
         return codec;
     }
 
+    // why the codec is not volatile ?
+    // this method always used by protocol update, and that thread deserved see the newest value of codec,
+    // the io thread will see the newest value after select(wakeup) too.
     public void setCodec(String codecId) throws IOException {
         if (inEventLoop()) {
             this.codec = context.getProtocolCodec(codecId);
@@ -357,10 +386,7 @@ public void setCodec(String codecId) throws IOException {
             if (codec == null) {
                 throw new IllegalArgumentException("codec not found");
             }
-            //FIXME .. is this work?
-            synchronized (this) {
-                this.codec = codec;
-            }
+            this.codec = codec;
         }
     }
 
@@ -397,7 +423,7 @@ public long getLastAccessTime() {
     }
 
     public int getLocalPort() {
-        return localPort;
+        return localPort & 0xffff;
     }
 
     public abstract int getOption(int name) throws IOException;
@@ -407,7 +433,7 @@ public String getRemoteAddr() {
     }
 
     public int getRemotePort() {
-        return remotePort;
+        return remotePort & 0xffff;
     }
 
     public SSLEngine getSSLEngine() {
@@ -426,9 +452,9 @@ private int guess_wrap_out(int src, int ext) {
         } else {
             int base = src + SslContext.SSL_PACKET_BUFFER_SIZE - 1;
             if (SslContext.OPENSSL_AVAILABLE) {
-                return (base / SslContext.SSL_PACKET_BUFFER_SIZE + 1) * ext + src;
+                return (base / SslContext.SSL_PACKET_BUFFER_SIZE + 1) * ext + src + 1;
             } else {
-                return (base / SslContext.SSL_PACKET_BUFFER_SIZE) * (ext + SslContext.SSL_PACKET_BUFFER_SIZE);
+                return (base / SslContext.SSL_PACKET_BUFFER_SIZE) * (ext + SslContext.SSL_PACKET_BUFFER_SIZE) + 1;
             }
         }
     }
@@ -438,6 +464,14 @@ public int hashCode() {
         return desc.hashCode();
     }
 
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof Channel) {
+            return ((Channel) obj).desc.equals(desc);
+        }
+        return false;
+    }
+
     public boolean inEventLoop() {
         return eventLoop.inEventLoop();
     }
@@ -483,10 +517,10 @@ public boolean isEnableSsl() {
      * 
      */
     private boolean isEnoughSslUnwrap(ByteBuf src) throws SSLException {
-        if (src.remaining() < 5) {
+        if (src.readableBytes() < 5) {
             return false;
         }
-        int pos = src.position();
+        int pos = src.readIndex();
         // TLS - Check ContentType
         int type = src.getUnsignedByte(pos);
         if (type < 20 || type > 23) {
@@ -501,14 +535,14 @@ private boolean isEnoughSslUnwrap(ByteBuf src) throws SSLException {
             throw NOT_TLS;
         }
         int len = packetLength + 5;
-        if (src.remaining() < len) {
+        if (src.readableBytes() < len) {
             return false;
         }
         if (len > SSL_PACKET_LIMIT) {
             throw SSL_PACKET_OVER_LIMIT;
         }
-        src.markL();
-        src.limit(pos + len);
+        src.markWriteIndex();
+        src.writeIndex(pos + len);
         return true;
     }
 
@@ -544,16 +578,17 @@ protected void read() throws Exception {
     }
 
     private void read_plain() throws Exception {
-        ByteBuf src = eventLoop.getReadBuf();
+        final Channel       ch    = this;
+        final ProtocolCodec codec = this.codec;
+        ByteBuf             dst   = codec.getPlainReadBuf(eventLoop, ch);
         for (; ; ) {
-            src.clear();
-            read_plain_remain(src);
-            if (!read_data(src)) {
+            codec.readPlainRemain(ch, dst);
+            if (!read_data(dst)) {
                 return;
             }
-            boolean full = src.isFullLimit();
-            accept(src);
-            if (!full) {
+            accept(dst);
+            // for epoll et mode
+            if (dst.hasWritableBytes()) {
                 break;
             }
         }
@@ -567,78 +602,70 @@ private void read_ssl() throws Exception {
             if (!read_data(src)) {
                 return;
             }
-            boolean full = src.isFullLimit();
             for (; ; ) {
                 if (isEnoughSslUnwrap(src)) {
                     ByteBuf res = unwrap(src);
                     if (res != null) {
                         accept(res);
                     }
-                    src.resetL();
-                    if (!src.hasRemaining()) {
+                    src.resetWriteIndex();
+                    if (!src.hasReadableBytes()) {
                         break;
                     }
                 } else {
-                    if (src.hasRemaining()) {
+                    if (src.hasReadableBytes()) {
                         slice_remain_ssl(src);
                     }
                     break;
                 }
             }
-            if (!full) {
+            // for epoll et mode
+            if (src.hasWritableBytes()) {
                 break;
             }
         }
     }
 
-    private boolean read_data(ByteBuf src) {
-        int len = native_read();
+    private boolean read_data(ByteBuf dst) {
+        int len = native_read(dst);
         if (len < 1) {
             if (len == -1) {
                 Util.close(this);
                 return false;
             }
-            store_remain(src.flip());
+            store_remain(dst);
             return false;
         }
-        if (Native.EPOLL_AVAILABLE) {
-            src.absLimit(src.absPos() + len);
-            src.absPos(0);
-        } else {
-            src.reverse();
-            src.flip();
-        }
+        dst.skipWrite(len);
         return true;
     }
 
     private void store_remain(ByteBuf src) {
-        if (src.hasRemaining()) {
+        if (src.hasReadableBytes()) {
             if (enable_ssl) {
                 slice_remain_ssl(src);
             } else {
-                slice_remain_plain(src);
+                codec.storePlainReadRemain(this, src);
             }
         }
     }
 
-    private void read_plain_remain(ByteBuf dst) {
-        ByteBuf remaining_buf = this.plain_remain_buf;
-        if (remaining_buf == null) {
-            return;
+    protected void read_plain_remain(ByteBuf dst) {
+        ByteBuf remain = this.plain_remain_buf;
+        if (remain != null) {
+            dst.writeBytes(remain);
+            remain.release();
+            this.plain_remain_buf = null;
         }
-        dst.putBytes(remaining_buf);
-        remaining_buf.release();
-        this.plain_remain_buf = null;
     }
 
     private void read_ssl_remain(ByteBuf dst) {
-        ByteBuf remaining_buf = this.ssl_remain_buf;
-        if (remaining_buf == null) {
-            return;
+        ByteBuf remain = this.ssl_remain_buf;
+        if (remain != null) {
+            dst.writeBytes(remain);
+            remain.release();
+            this.ssl_remain_buf = null;
         }
-        dst.putBytes(remaining_buf);
-        remaining_buf.release();
-        this.ssl_remain_buf = null;
     }
 
     public void release(Frame frame) {
@@ -716,21 +743,26 @@ private void safe_close() {
             release(ssl_remain_buf);
             release(plain_remain_buf);
             close_channel();
+            channel_establish();
             fire_closed();
             stop_context();
         }
     }
 
+    private void channel_establish() {
+        context.channelEstablish(this, CLOSED_CHANNEL);
+    }
+
     abstract void close_channel();
 
     public abstract void setOption(int name, int value) throws IOException;
 
     private ByteBuf slice_remain(ByteBuf src) {
-        int remain = src.remaining();
+        int remain = src.readableBytes();
         if (remain > 0) {
             ByteBuf remaining = alloc().allocate(remain);
-            remaining.putBytes(src);
-            return remaining.flip();
+            remaining.writeBytes(src);
+            return remaining;
         } else {
             return null;
         }
@@ -744,15 +776,16 @@ private void stop_context() {
 
     //FIXME 部分buf不需要swap
     private ByteBuf swap(ByteBufAllocator allocator, ByteBuf buf) {
-        ByteBuf out = allocator.allocate(buf.limit());
-        out.putBytes(buf);
-        return out.flip();
+        // use writeIndex instead of readableBytes because of the buf readIndex always be zero.
+        ByteBuf out = allocator.allocate(buf.writeIndex());
+        out.writeBytes(buf);
+        return out;
     }
 
     private void sync_buf(SSLEngineResult result, ByteBuf src, ByteBuf dst) {
         //FIXME 同步。。。。。
-        src.reverse();
-        dst.reverse();
+        src.reverseRead();
+        dst.reverseWrite();
         //      int bytesConsumed = result.bytesConsumed();
         //      int bytesProduced = result.bytesProduced();
         //      if (bytesConsumed > 0) {
@@ -772,9 +805,8 @@ private ByteBuf unwrap(ByteBuf src) throws IOException {
         SSLEngine ssl_engine = getSSLEngine();
         ByteBuf   dst        = FastThreadLocal.get().getSslUnwrapBuf();
         if (ssl_handshake_finished) {
-            dst.clear();
-            read_plain_remain(dst);
-            SSLEngineResult result = ssl_engine.unwrap(src.nioBuffer(), dst.nioBuffer());
+            codec.readPlainRemain(this, dst);
+            SSLEngineResult result = ssl_engine.unwrap(src.nioReadBuffer(), dst.nioWriteBuffer());
             if (result.getStatus() == Status.BUFFER_OVERFLOW) {
                 //why throw an exception here instead of handle it?
                 //the getSslUnwrapBuf will return an thread local buffer for unwrap,
@@ -783,12 +815,12 @@ private ByteBuf unwrap(ByteBuf src) throws IOException {
                 //one EventLoop only have one buffer,but before do unwrap, every channel maybe cached a large
                 //buffer under SSL_UNWRAP_BUFFER_SIZE,I do not think it is a good way to cached much memory in
                 //channel, it is not friendly for load much channels in one system, if you get exception here,
-                //you may need find a way to limit you frame size,or cache your incomplete frame's data to
+                //you may need find a way to writeIndex you frame size,or cache your incomplete frame's data to
                 //file system or others way.
                 throw SSL_UNWRAP_OVER_LIMIT;
             }
             sync_buf(result, src, dst);
-            return dst.flip();
+            return dst;
         } else {
             for (; ; ) {
                 dst.clear();
@@ -805,10 +837,20 @@ private ByteBuf unwrap(ByteBuf src) throws IOException {
                     finish_handshake();
                     return null;
                 } else if (handshakeStatus == HandshakeStatus.NEED_UNWRAP) {
-                    if (src.hasRemaining()) {
+                    if (src.hasReadableBytes()) {
                         continue;
                     }
                     return null;
+                } else if (handshakeStatus == HandshakeStatus.NOT_HANDSHAKING) {
+                    // NOTICE: this handle may not the NOT_HANDSHAKING expected
+                    // NOT_HANDSHAKING is mean closed in wildfly-openssl.unwrap, so do not do finish_handshake
+                    // see: https://stackoverflow.com/questions/31149383/difference-between-not-handshaking-and-finished
+                    if (SSL_DEBUG) {
+                        logger.error("unwrap handle status: NOT_HANDSHAKING({})", this);
+                    }
+                    throw SSL_UNWRAP_CLOSED;
+                } else if (result.getStatus() == Status.BUFFER_OVERFLOW) {
+                    throw SSL_UNWRAP_OVER_LIMIT;
                 }
             }
         }
@@ -816,7 +858,7 @@ private ByteBuf unwrap(ByteBuf src) throws IOException {
 
     private static SSLEngineResult unwrap(SSLEngine ssl_engine, ByteBuf src, ByteBuf dst) throws SSLException {
         try {
-            return ssl_engine.unwrap(src.nioBuffer(), dst.nioBuffer());
+            return ssl_engine.unwrap(src.nioReadBuffer(), dst.nioWriteBuffer());
         } catch (SSLException e) {
             logger.error(e.getMessage());
             debugException(logger, e);
@@ -832,64 +874,68 @@ private ByteBuf wrap(ByteBuf src) throws IOException {
             if (ssl_handshake_finished) {
                 byte sslWrapExt = this.ssl_wrap_ext;
                 if (sslWrapExt == 0) {
-                    out = alloc.allocate(guess_wrap_out(src.remaining(), 0xff + 1));
+                    out = alloc.allocate(guess_wrap_out(src.readableBytes(), 0xff + 1));
                 } else {
-                    out = alloc.allocate(guess_wrap_out(src.remaining(), sslWrapExt & 0xff));
+                    out = alloc.allocate(guess_wrap_out(src.readableBytes(), sslWrapExt & 0xff));
                 }
                 final int SSL_PACKET_BUFFER_SIZE = SslContext.SSL_PACKET_BUFFER_SIZE;
                 for (; ; ) {
-                    SSLEngineResult result = engine.wrap(src.nioBuffer(), out.nioBuffer());
+                    SSLEngineResult result = engine.wrap(src.nioReadBuffer(), out.nioWriteBuffer());
                     Status          status = result.getStatus();
                     sync_buf(result, src, out);
                     if (status == Status.CLOSED) {
-                        return out.flip();
+                        return out;
                     } else if (status == Status.BUFFER_OVERFLOW) {
                         out.expansion(out.capacity() + SSL_PACKET_BUFFER_SIZE);
                         continue;
                     } else {
-                        if (src.hasRemaining()) {
+                        if (src.hasReadableBytes()) {
                             continue;
                         }
                         if (sslWrapExt == 0) {
-                            int srcLen = src.limit();
-                            int outLen = out.position();
+                            int srcLen = src.writeIndex();
+                            int outLen = out.readIndex();
                             int y      = ((srcLen + 1) / SSL_PACKET_BUFFER_SIZE) + 1;
                             int u      = ((outLen - srcLen) / y) * 2;
                             this.ssl_wrap_ext = (byte) u;
                         }
-                        return out.flip();
+                        return out;
                     }
                 }
             } else {
                 ByteBuf dst = FastThreadLocal.get().getSslWrapBuf();
                 for (; ; ) {
                     dst.clear();
-                    SSLEngineResult result          = engine.wrap(src.nioBuffer(), dst.nioBuffer());
+                    SSLEngineResult result          = engine.wrap(src.nioReadBuffer(), dst.nioWriteBuffer());
                     Status          status          = result.getStatus();
                     HandshakeStatus handshakeStatus = result.getHandshakeStatus();
                     sync_buf(result, src, dst);
                     if (status == Status.CLOSED) {
-                        return swap(alloc, dst.flip());
+                        return swap(alloc, dst);
                     }
                     if (handshakeStatus == HandshakeStatus.NEED_UNWRAP) {
                         if (out != null) {
-                            out.putBytes(dst.flip());
-                            return out.flip();
+                            out.writeBytes(dst);
+                            return out;
                         }
-                        return swap(alloc, dst.flip());
+                        return swap(alloc, dst);
                     } else if (handshakeStatus == HandshakeStatus.NEED_WRAP) {
                         if (out == null) {
                             out = alloc.allocate(256);
                         }
-                        out.putBytes(dst.flip());
+                        out.writeBytes(dst);
                         continue;
                     } else if (handshakeStatus == HandshakeStatus.FINISHED) {
                         finish_handshake();
                         if (out != null) {
-                            out.putBytes(dst.flip());
-                            return out.flip();
+                            out.writeBytes(dst);
+                            return out;
                         }
-                        return swap(alloc, dst.flip());
+                        return swap(alloc, dst);
+                    } else if (handshakeStatus == HandshakeStatus.NOT_HANDSHAKING) {
+                        // NOTICE: this handle may not the NOT_HANDSHAKING expected
+                        // It is shouldn't here to have "NOT_HANDSHAKING", because of the ssl is closed?
+                        throw SSL_WRAP_CLOSED;
                     } else if (handshakeStatus == HandshakeStatus.NEED_TASK) {
                         run_delegated_tasks(engine);
                         continue;
@@ -911,7 +957,7 @@ public void write(ByteBuf buf) {
                 ByteBuf old = buf;
                 try {
                     buf = wrap(old);
-                } catch (Exception e) {
+                } catch (Throwable e) {
                     debugException(logger, e);
                 } finally {
                     old.release();
@@ -942,9 +988,14 @@ public void writeAndFlush(Frame frame) throws Exception {
         flush();
     }
 
+    @Override
+    protected AttributeKeys getKeys() {
+        return getKeys(Channel.class);
+    }
+
     abstract boolean isInterestWrite();
 
-    abstract int native_read();
+    abstract int native_read(ByteBuf dst);
 
     static final class EpollChannel extends Channel {
 
@@ -977,9 +1028,9 @@ boolean isInterestWrite() {
         }
 
         @Override
-        int native_read() {
-            ByteBuf buf = eventLoop.getReadBuf();
-            return Native.read(fd, eventLoop.getBufAddress() + buf.absPos(), buf.remaining());
+        int native_read(ByteBuf dst) {
+            long address = dst.address() + dst.absWriteIndex();
+            return Native.read(fd, address, dst.writableBytes());
         }
 
         @Override
@@ -1010,13 +1061,13 @@ int write() {
                 }
                 if (cw_len == 1) {
                     ByteBuf buf     = cwb_array[0];
-                    long    address = buf.address() + buf.absPos();
-                    int     len     = Native.write(fd, address, buf.remaining());
+                    long    address = buf.address() + buf.absReadIndex();
+                    int     len     = Native.write(fd, address, buf.readableBytes());
                     if (len == -1) {
                         return -1;
                     }
-                    buf.skip(len);
-                    if (buf.hasRemaining()) {
+                    buf.skipRead(len);
+                    if (buf.hasReadableBytes()) {
                         this.current_wbs_len = 1;
                         this.interestWrite = true;
                         return 0;
@@ -1034,9 +1085,9 @@ int write() {
                     long iov_pos = iovec;
                     for (int i = 0; i < cw_len; i++) {
                         ByteBuf buf = cwb_array[i];
-                        Unsafe.putLong(iov_pos, buf.address() + buf.absPos());
+                        Unsafe.putLong(iov_pos, buf.address() + buf.absReadIndex());
                         iov_pos += 8;
-                        Unsafe.putLong(iov_pos, buf.remaining());
+                        Unsafe.putLong(iov_pos, buf.readableBytes());
                         iov_pos += 8;
                     }
                     long len = Native.writev(fd, iovec, cw_len);
@@ -1045,14 +1096,14 @@ int write() {
                     }
                     for (int i = 0; i < cw_len; i++) {
                         ByteBuf buf = cwb_array[i];
-                        int     r   = buf.remaining();
+                        int     r   = buf.readableBytes();
                         if (len < r) {
-                            buf.skip((int) len);
+                            buf.skipRead((int) len);
                             int remain = cw_len - i;
                             System.arraycopy(cwb_array, i, cwb_array, 0, remain);
                             fill_null(cwb_array, remain, cw_len);
                             this.interestWrite = true;
-                            this.current_wbs_len = remain;
+                            this.current_wbs_len = (byte) remain;
                             return 0;
                         } else {
                             len -= r;
@@ -1133,7 +1184,7 @@ boolean isInterestWrite() {
         private int native_write(ByteBuffer src) {
             try {
                 return channel.write(src);
-            } catch (IOException e) {
+            } catch (Throwable e) {
                 return -1;
             }
         }
@@ -1141,16 +1192,16 @@ private int native_write(ByteBuffer src) {
         private long native_write(ByteBuffer[] srcs, int len) {
             try {
                 return channel.write(srcs, 0, len);
-            } catch (IOException e) {
+            } catch (Throwable e) {
                 return -1;
             }
         }
 
         @Override
-        int native_read() {
+        int native_read(ByteBuf dst) {
             try {
-                return channel.read(eventLoop.getReadBuf().nioBuffer());
-            } catch (IOException e) {
+                return channel.read(dst.nioWriteBuffer());
+            } catch (Throwable e) {
                 return -1;
             }
         }
@@ -1189,14 +1240,14 @@ int write() {
                 }
                 if (cwb_len == 1) {
                     ByteBuf    buf    = cwb_array[0];
-                    ByteBuffer nioBuf = buf.nioBuffer();
+                    ByteBuffer nioBuf = buf.nioReadBuffer();
                     int        len    = native_write(nioBuf);
                     if (len == -1) {
                         return -1;
                     }
                     if (nioBuf.hasRemaining()) {
                         this.current_wbs_len = 1;
-                        buf.reverse();
+                        buf.reverseRead();
                         interestWrite();
                         return 0;
                     } else {
@@ -1210,7 +1261,7 @@ int write() {
                     }
                 } else {
                     for (int i = 0; i < cwb_len; i++) {
-                        wb_array[i] = cwb_array[i].nioBuffer();
+                        wb_array[i] = cwb_array[i].nioReadBuffer();
                     }
                     long len = native_write(wb_array, cwb_len);
                     if (len == -1) {
@@ -1219,13 +1270,13 @@ int write() {
                     for (int i = 0; i < cwb_len; i++) {
                         ByteBuf buf = cwb_array[i];
                         if (wb_array[i].hasRemaining()) {
-                            buf.reverse();
+                            buf.reverseRead();
                             int remain = cwb_len - i;
                             System.arraycopy(cwb_array, i, cwb_array, 0, remain);
                             fill_null(cwb_array, remain, cwb_len);
                             fill_null(wb_array, i, cwb_len);
                             interestWrite();
-                            this.current_wbs_len = remain;
+                            this.current_wbs_len = (byte) remain;
                             return 0;
                         } else {
                             wb_array[i] = null;
@@ -1279,7 +1330,7 @@ private static Field OPENSSL_DESTROYED() {
 
         static boolean isOpensslEngineDestroyed(SSLEngine sslEngine) {
             try {
-                return ((Integer) OPENSSL_DESTROYED.get(sslEngine)) == 1;
+                return ((Integer) OPENSSL_DESTROYED.get(sslEngine)) != 0;
             } catch (IllegalAccessException e) {
                 throw new RuntimeException(e);
             }
diff --git a/firenio-core/src/main/java/com/firenio/component/ChannelAcceptor.java b/firenio-core/src/main/java/com/firenio/component/ChannelAcceptor.java
index 6cc7f69aa..11a2d09f2 100644
--- a/firenio-core/src/main/java/com/firenio/component/ChannelAcceptor.java
+++ b/firenio-core/src/main/java/com/firenio/component/ChannelAcceptor.java
@@ -146,6 +146,11 @@ public synchronized void unbind() {
         Util.stop(this);
     }
 
+    @Override
+    public String toString() {
+        return (unsafe instanceof EpollAcceptorUnsafe ? "Epoll" : "Jdk") + "Acceptor(" + getServerAddress() + ")";
+    }
+
     static abstract class AcceptorUnsafe implements Closeable {
 
         abstract void bind(NioEventLoop el, ChannelAcceptor a, int backlog) throws IOException;
diff --git a/firenio-core/src/main/java/com/firenio/component/ChannelActiveListener.java b/firenio-core/src/main/java/com/firenio/component/ChannelActiveListener.java
index 152cbb3b5..53fee7631 100644
--- a/firenio-core/src/main/java/com/firenio/component/ChannelActiveListener.java
+++ b/firenio-core/src/main/java/com/firenio/component/ChannelActiveListener.java
@@ -24,7 +24,7 @@ public class ChannelActiveListener implements ChannelIdleListener {
     private Logger logger = LoggerFactory.getLogger(getClass());
 
     @Override
-    public void channelIdled(Channel ch, long lastIdleTime, long currentTime) {
+    public void channelIdled(Channel ch, long lastIdleTime) {
         if (ch.getLastAccessTime() < lastIdleTime) {
             logger.info("disconnect(hb) {}", ch);
             Util.close(ch);
diff --git a/firenio-core/src/main/java/com/firenio/component/ChannelAliveListener.java b/firenio-core/src/main/java/com/firenio/component/ChannelAliveListener.java
index 2c15dcd27..8185cf173 100644
--- a/firenio-core/src/main/java/com/firenio/component/ChannelAliveListener.java
+++ b/firenio-core/src/main/java/com/firenio/component/ChannelAliveListener.java
@@ -24,7 +24,7 @@ public class ChannelAliveListener implements ChannelIdleListener {
     private Logger logger = LoggerFactory.getLogger(getClass());
 
     @Override
-    public void channelIdled(Channel ch, long lastIdleTime, long currentTime) {
+    public void channelIdled(Channel ch, long lastIdleTime) {
         if (ch.getLastAccessTime() < lastIdleTime && matched(ch)) {
             logger.info("disconnect(hb) {}", ch);
             Util.close(ch);
diff --git a/firenio-core/src/main/java/com/firenio/component/ChannelConnector.java b/firenio-core/src/main/java/com/firenio/component/ChannelConnector.java
index a238a5a5d..76c2b2847 100644
--- a/firenio-core/src/main/java/com/firenio/component/ChannelConnector.java
+++ b/firenio-core/src/main/java/com/firenio/component/ChannelConnector.java
@@ -19,6 +19,7 @@
 import java.io.IOException;
 import java.net.InetAddress;
 import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
 import java.nio.channels.SocketChannel;
 
 import com.firenio.Develop;
@@ -39,12 +40,12 @@
 public final class ChannelConnector extends ChannelContext implements Closeable {
 
     private static final Logger                 logger      = LoggerFactory.getLogger(ChannelConnector.class);
-    private volatile     Callback      callback;
-    private volatile     boolean                callback_ed = true;
     private              Channel                ch;
     private              NioEventLoop           eventLoop;
-    private volatile     DelayedQueue.DelayTask timeoutTask;
     private              ConnectorUnsafe        unsafe;
+    private volatile     Callback      callback;
+    private volatile     boolean                callback_ed = true;
+    private volatile     DelayedQueue.DelayTask timeoutTask;
 
     public ChannelConnector(int port) {
         this("127.0.0.1", port);
@@ -64,11 +65,6 @@ public ChannelConnector(NioEventLoopGroup group, String host, int port) {
         if (!group.isSharable() && !group.isRunning()) {
             group.setEventLoopSize(1);
         }
-        if (Native.EPOLL_AVAILABLE) {
-            unsafe = new EpollConnectorUnsafe();
-        } else {
-            unsafe = new JavaConnectorUnsafe();
-        }
     }
 
     public ChannelConnector(String host, int port) {
@@ -78,9 +74,9 @@ public ChannelConnector(String host, int port) {
     @Override
     protected void channelEstablish(Channel ch, Throwable ex) {
         if (!callback_ed) {
-            this.unsafe.channelEstablish(ch, eventLoop, ex);
             this.ch = ch;
             this.callback_ed = true;
+            this.unsafe.channelEstablish(ch, ex);
             this.timeoutTask.cancel();
             try {
                 this.callback.call(ch, ex);
@@ -94,10 +90,6 @@ protected void channelEstablish(Channel ch, Throwable ex) {
     public synchronized void close() {
         Util.close(ch);
         Util.stop(this);
-        if (!getProcessorGroup().isSharable()) {
-            this.eventLoop = null;
-        }
-        this.ch = null;
     }
 
     public synchronized Channel connect() throws Exception {
@@ -118,12 +110,17 @@ public synchronized void connect(Callback callback, long timeout) throw
             throw new IOException("connect is pending");
         }
         this.callback_ed = false;
-        this.timeoutTask = new TimeoutTask(this, timeout);
         this.callback = callback;
+        this.timeoutTask = new TimeoutTask(this, timeout);
         this.getProcessorGroup().setContext(this);
+        if (Native.EPOLL_AVAILABLE) {
+            unsafe = new EpollConnectorUnsafe();
+        } else {
+            unsafe = new JavaConnectorUnsafe();
+        }
         Util.start(getProcessorGroup());
         Util.start(this);
-        if (eventLoop == null) {
+        if (eventLoop == null || !eventLoop.isRunning()) {
             eventLoop = getProcessorGroup().getNext();
         }
         boolean submitted = this.eventLoop.submit(new Runnable() {
@@ -152,17 +149,9 @@ public synchronized Channel connect(long timeout) throws Exception {
         // If your application blocking here, check if you are blocking the io thread.
         // Notice that do not blocking io thread at any time.
         callback.await();
-        if (callback.isTimeout()) {
-            Util.close(this);
-            throw new TimeoutException("connect to " + getServerAddress() + " time out");
-        }
         if (callback.isFailed()) {
             Util.close(this);
-            Throwable ex = callback.getThrowable();
-            if (ex instanceof Exception) {
-                throw (Exception) callback.getThrowable();
-            }
-            throw new IOException("connect failed", ex);
+            throw new IOException("connect failed", callback.getThrowable());
         }
         return getChannel();
     }
@@ -202,14 +191,15 @@ static abstract class ConnectorUnsafe {
 
         abstract void connect(ChannelConnector ctx, NioEventLoop el) throws IOException;
 
-        abstract void channelEstablish(Channel ch, NioEventLoop el, Throwable ex);
+        abstract void channelEstablish(Channel ch, Throwable ex);
 
     }
 
     static final class EpollConnectorUnsafe extends ConnectorUnsafe {
 
-        private int    fd = -1;
-        private String remoteAddr;
+        private int            fd = -1;
+        private String         remoteAddr;
+        private EpollEventLoop el;
 
         @Override
         void connect(ChannelConnector ctx, NioEventLoop el) throws IOException {
@@ -219,28 +209,28 @@ void connect(ChannelConnector ctx, NioEventLoop el) throws IOException {
             int fd = Native.connect(host.getHostAddress(), ctx.getPort());
             Native.throwException(fd);
             this.fd = fd;
-            el.schedule(ctx.timeoutTask);
+            this.el = un;
             un.ctxs.put(fd, ctx);
+            el.schedule(ctx.timeoutTask);
             int res = Native.epoll_add(un.epfd, fd, Native.EPOLL_OUT);
             Native.throwException(res);
         }
 
         @Override
-        void channelEstablish(Channel ch, NioEventLoop el, Throwable ex) {
+        void channelEstablish(Channel ch, Throwable ex) {
             if (ex != null && fd != -1) {
-                EpollEventLoop un = (EpollEventLoop) el;
-                un.ctxs.remove(fd);
+                el.ctxs.remove(fd);
                 if (Develop.NATIVE_DEBUG) {
-                    int res = Native.epoll_del(un.epfd, fd);
+                    int res = Native.epoll_del(el.epfd, fd);
                     if (res == -1) {
-                        logger.error("cancel...epfd:{},fd:{}", un.epfd, fd);
+                        logger.error("cancel...epfd:{},fd:{}", el.epfd, fd);
                     }
                     res = Native.close(fd);
                     if (res == -1) {
                         logger.error("cancel...fd:{}", fd);
                     }
                 } else {
-                    Native.epoll_del(un.epfd, fd);
+                    Native.epoll_del(el.epfd, fd);
                     Native.close(fd);
                 }
                 this.fd = -1;
@@ -251,25 +241,22 @@ String getRemoteAddr() {
             return remoteAddr;
         }
 
-        int getFd() {
-            return fd;
-        }
-
     }
 
     static final class JavaConnectorUnsafe extends ConnectorUnsafe {
 
         private SocketChannel javaChannel;
+        private SelectionKey  selectionKey;
 
         @Override
         void connect(ChannelConnector ctx, NioEventLoop el) throws IOException {
-            Util.close(javaChannel);
             this.javaChannel = SocketChannel.open();
             this.javaChannel.configureBlocking(false);
             if (!javaChannel.connect(ctx.getServerAddress())) {
                 el.schedule(ctx.timeoutTask);
                 JavaEventLoop elUnsafe = (JavaEventLoop) el;
-                javaChannel.register(elUnsafe.getSelector(), SelectionKey.OP_CONNECT, ctx);
+                Selector      selector = elUnsafe.getSelector();
+                this.selectionKey = javaChannel.register(selector, SelectionKey.OP_CONNECT, ctx);
             }
         }
 
@@ -278,16 +265,10 @@ SocketChannel getSelectableChannel() {
         }
 
         @Override
-        void channelEstablish(Channel ch, NioEventLoop el, Throwable ex) {
-            final SocketChannel channel = this.javaChannel;
-            if (ex != null && channel != null) {
-                final JavaEventLoop un  = (JavaEventLoop) el;
-                SelectionKey        key = channel.keyFor(un.getSelector());
-                if (key != null) {
-                    key.cancel();
-                }
-                Util.close(channel);
-                this.javaChannel = null;
+        void channelEstablish(Channel ch, Throwable ex) {
+            if (ex != null) {
+                selectionKey.cancel();
+                Util.close(javaChannel);
             }
         }
 
diff --git a/firenio-core/src/main/java/com/firenio/component/ChannelContext.java b/firenio-core/src/main/java/com/firenio/component/ChannelContext.java
index ebff8940e..50e4e9d34 100644
--- a/firenio-core/src/main/java/com/firenio/component/ChannelContext.java
+++ b/firenio-core/src/main/java/com/firenio/component/ChannelContext.java
@@ -33,6 +33,7 @@
 import com.firenio.common.Assert;
 import com.firenio.common.FileUtil;
 import com.firenio.common.Properties;
+import com.firenio.common.Unsafe;
 import com.firenio.common.Util;
 import com.firenio.concurrent.EventLoop;
 import com.firenio.concurrent.EventLoopGroup;
@@ -148,19 +149,29 @@ protected void doStart() throws Exception {
             }
             if (isEnableSsl()) {
                 sb.setLength(0);
-                for (String p : SslContext.ENABLED_PROTOCOLS) {
+                for (String p : sslContext.getProtocols()) {
                     sb.append(p);
                     sb.append(',');
                     sb.append(' ');
                 }
                 sb.setLength(sb.length() - 2);
-                logger.info("ssl default protocols : [ {} ]", sb.toString());
+                logger.info("ssl protocols         : [ {} ]", sb.toString());
+            }
+            if (isEnableSsl()) {
+                sb.setLength(0);
+                for (String p : sslContext.getCipherSuites()) {
+                    sb.append(p);
+                    sb.append(',');
+                    sb.append(' ');
+                }
+                sb.setLength(sb.length() - 2);
+                logger.info("ssl cipher suites     : [ {} ]", sb.toString());
             }
         }
     }
 
     private String getByteBufPoolType(NioEventLoopGroup g) {
-        if (Options.isEnableUnsafeBuf()) {
+        if (Unsafe.UNSAFE_BUF_AVAILABLE) {
             return "unsafe";
         }
         return g.isEnableMemoryPoolDirect() ? "direct" : "heap";
diff --git a/firenio-core/src/main/java/com/firenio/component/ChannelIdleListener.java b/firenio-core/src/main/java/com/firenio/component/ChannelIdleListener.java
index ae5c1da1d..5f337df55 100644
--- a/firenio-core/src/main/java/com/firenio/component/ChannelIdleListener.java
+++ b/firenio-core/src/main/java/com/firenio/component/ChannelIdleListener.java
@@ -19,6 +19,6 @@
 
 public interface ChannelIdleListener extends EventListener {
 
-    void channelIdled(Channel ch, long lastIdleTime, long currentTime);
+    void channelIdled(Channel ch, long lastIdleTime);
 
 }
diff --git a/firenio-core/src/main/java/com/firenio/component/ChannelManager.java b/firenio-core/src/main/java/com/firenio/component/ChannelManager.java
index 96ca37278..51d2c531d 100644
--- a/firenio-core/src/main/java/com/firenio/component/ChannelManager.java
+++ b/firenio-core/src/main/java/com/firenio/component/ChannelManager.java
@@ -44,18 +44,26 @@ public static void broadcast(ByteBuf buf, Collection chs) {
         }
     }
 
+    public void broadcast(ByteBuf buf) {
+        broadcast(buf, channels.values());
+    }
+
     public static void broadcast(Frame frame, Collection chs) throws Exception {
         if (chs.size() == 0) {
+            frame.release();
             return;
         }
         Channel ch = chs.iterator().next();
-        if (ch != null) {
-            broadcast(ch.encode(frame), chs);
+        if (ch == null) {
+            frame.release();
+            return;
+        }
+        try {
+            ByteBuf buf = ch.getCodec().encode(ch, frame);
+            broadcast(buf, chs);
+        } finally {
+            frame.release();
         }
-    }
-
-    public void broadcast(ByteBuf buf) {
-        broadcast(buf, channels.values());
     }
 
     public void broadcast(Frame frame) throws Exception {
diff --git a/firenio-core/src/main/java/com/firenio/component/ExceptionCaughtHandle.java b/firenio-core/src/main/java/com/firenio/component/ExceptionCaughtHandle.java
index afeb8ffa4..85dfb56d0 100644
--- a/firenio-core/src/main/java/com/firenio/component/ExceptionCaughtHandle.java
+++ b/firenio-core/src/main/java/com/firenio/component/ExceptionCaughtHandle.java
@@ -20,6 +20,6 @@
  */
 public interface ExceptionCaughtHandle {
 
-    void exceptionCaught(Channel ch, Frame frame, Exception ex);
+    void exceptionCaught(Channel ch, Frame frame, Throwable ex);
 
 }
diff --git a/firenio-core/src/main/java/com/firenio/component/FastThreadLocal.java b/firenio-core/src/main/java/com/firenio/component/FastThreadLocal.java
index 5a24128ec..252f1ca4b 100644
--- a/firenio-core/src/main/java/com/firenio/component/FastThreadLocal.java
+++ b/firenio-core/src/main/java/com/firenio/component/FastThreadLocal.java
@@ -23,28 +23,27 @@
 import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import com.firenio.buffer.ByteBuf;
-import com.firenio.collection.AttributesImpl;
+import com.firenio.collection.AttributeKey;
+import com.firenio.collection.AttributeMap;
 import com.firenio.common.Util;
 
 /**
  * @author wangkai
  */
-public final class FastThreadLocal extends AttributesImpl {
+public final class FastThreadLocal extends AttributeMap {
 
-    private static final AtomicInteger                indexedVarsIndex   = new AtomicInteger(0);
-    private static final int                          maxIndexedVarsSize = 32;
-    private static final ThreadLocal slowThreadLocal    = new ThreadLocal<>();
+    private static final ThreadLocal slowThreadLocal = new ThreadLocal<>();
 
-    private byte[]                       bytes32          = new byte[32];
-    private Map charsetDecoders  = new IdentityHashMap<>();
-    private Map charsetEncoders  = new IdentityHashMap<>();
-    private Object[]                     indexedVariables = new Object[maxIndexedVarsSize];
+    private byte[]                       bytes32         = new byte[32];
+    private Map charsetDecoders = new IdentityHashMap<>();
+    private Map charsetEncoders = new IdentityHashMap<>();
     private ByteBuf                      sslUnwrapBuf;
     private ByteBuf                      sslWrapBuf;
-    private StringBuilder                stringBuilder    = new StringBuilder(512);
+    private StringBuilder                stringBuilder   = new StringBuilder(512);
+    private List                      list            = new ArrayList<>();
+    private Map                    map             = new HashMap<>();
 
     FastThreadLocal() {}
 
@@ -75,15 +74,12 @@ public static FastThreadLocal get() {
         }
     }
 
-    public static int nextIndexedVariablesIndex() {
-        if (indexedVarsIndex.get() >= maxIndexedVarsSize) {
-            return -1;
-        }
-        int index = indexedVarsIndex.getAndIncrement();
-        if (index >= maxIndexedVarsSize) {
-            return -1;
-        }
-        return index;
+    public static AttributeKey valueOfKey(String name) {
+        return AttributeMap.valueOfKey(FastThreadLocal.class, name);
+    }
+
+    public static AttributeKey valueOfKey(String name, AttributeInitFunction function) {
+        return AttributeMap.valueOfKey(FastThreadLocal.class, name, function);
     }
 
     private void destroy0() {
@@ -113,40 +109,16 @@ public CharsetEncoder getCharsetEncoder(Charset charset) {
         return encoder;
     }
 
-    public Object getIndexedVariable(int index) {
-        return indexedVariables[index];
-    }
-
-    public List getList(int index) {
-        List list = (List) getIndexedVariable(index);
-        if (list == null) {
-            list = new ArrayList<>();
-            setIndexedVariable(index, list);
-        }
-        list.clear();
-        return list;
-    }
-
-    public Map getMap(int index) {
-        Map map = (Map) getIndexedVariable(index);
-        if (map == null) {
-            map = new HashMap<>();
-            setIndexedVariable(index, map);
-        }
-        map.clear();
-        return map;
-    }
-
     public ByteBuf getSslUnwrapBuf() {
         if (sslUnwrapBuf == null) {
-            sslUnwrapBuf = ByteBuf.direct(SslContext.SSL_UNWRAP_BUFFER_SIZE);
+            sslUnwrapBuf = ByteBuf.buffer(SslContext.SSL_UNWRAP_BUFFER_SIZE);
         }
         return sslUnwrapBuf;
     }
 
     public ByteBuf getSslWrapBuf() {
         if (sslWrapBuf == null) {
-            sslWrapBuf = ByteBuf.direct(SslContext.SSL_PACKET_BUFFER_SIZE);
+            sslWrapBuf = ByteBuf.buffer(SslContext.SSL_PACKET_BUFFER_SIZE);
         }
         return sslWrapBuf;
     }
@@ -156,8 +128,18 @@ public StringBuilder getStringBuilder() {
         return stringBuilder;
     }
 
-    public void setIndexedVariable(int index, Object value) {
-        indexedVariables[index] = value;
+    public List getList() {
+        list.clear();
+        return list;
     }
 
+    public Map getMap() {
+        map.clear();
+        return map;
+    }
+
+    @Override
+    protected AttributeKeys getKeys() {
+        return getKeys(FastThreadLocal.class);
+    }
 }
diff --git a/firenio-core/src/main/java/com/firenio/component/Frame.java b/firenio-core/src/main/java/com/firenio/component/Frame.java
index 36191b8ef..4efa9263b 100644
--- a/firenio-core/src/main/java/com/firenio/component/Frame.java
+++ b/firenio-core/src/main/java/com/firenio/component/Frame.java
@@ -81,7 +81,7 @@ public void setBytes(byte[] bytes, int off, int len, Channel ch) {
     }
 
     public void setBytes(int header, byte[] bytes, int off, int len) {
-        this.content = ByteBuf.heap(header + len).skip(header);
+        this.content = ByteBuf.buffer(header + len).skipWrite(header);
         write(bytes, off, len);
     }
 
@@ -98,7 +98,7 @@ public void write(byte[] bytes, int off, int len) {
         if (c == null) {
             throw new NullPointerException("do setContent(buf) before write");
         }
-        c.putBytes(bytes, off, len);
+        c.writeBytes(bytes, off, len);
     }
 
     public void write(String text, Channel ch) {
diff --git a/firenio-core/src/main/java/com/firenio/component/IoEventHandle.java b/firenio-core/src/main/java/com/firenio/component/IoEventHandle.java
index afec0a0db..d9512b0fe 100644
--- a/firenio-core/src/main/java/com/firenio/component/IoEventHandle.java
+++ b/firenio-core/src/main/java/com/firenio/component/IoEventHandle.java
@@ -25,7 +25,7 @@ public abstract class IoEventHandle implements ExceptionCaughtHandle {
     public abstract void accept(Channel ch, Frame frame) throws Exception;
 
     @Override
-    public void exceptionCaught(Channel ch, Frame frame, Exception ex) {
+    public void exceptionCaught(Channel ch, Frame frame, Throwable ex) {
         logger.error(ex.getMessage(), ex);
     }
 
diff --git a/firenio-core/src/main/java/com/firenio/component/LoggerExceptionCaughtHandle.java b/firenio-core/src/main/java/com/firenio/component/LoggerExceptionCaughtHandle.java
index 2a79c4145..0e71daacd 100644
--- a/firenio-core/src/main/java/com/firenio/component/LoggerExceptionCaughtHandle.java
+++ b/firenio-core/src/main/java/com/firenio/component/LoggerExceptionCaughtHandle.java
@@ -26,7 +26,7 @@ public class LoggerExceptionCaughtHandle implements ExceptionCaughtHandle {
     private Logger logger = LoggerFactory.getLogger(getClass());
 
     @Override
-    public void exceptionCaught(Channel ch, Frame frame, Exception ex) {
+    public void exceptionCaught(Channel ch, Frame frame, Throwable ex) {
         logger.error(ex.getMessage(), ex);
     }
 
diff --git a/firenio-core/src/main/java/com/firenio/component/Native.java b/firenio-core/src/main/java/com/firenio/component/Native.java
index 1504a2f05..0ff6545cc 100644
--- a/firenio-core/src/main/java/com/firenio/component/Native.java
+++ b/firenio-core/src/main/java/com/firenio/component/Native.java
@@ -2,13 +2,11 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 
 import com.firenio.Develop;
 import com.firenio.Options;
 import com.firenio.common.FileUtil;
 import com.firenio.common.Unsafe;
-import com.firenio.common.Util;
 import com.firenio.log.Logger;
 import com.firenio.log.LoggerFactory;
 
@@ -18,54 +16,71 @@ public class Native {
     //gcc -shared -g -fPIC -m64 -o obj/native.o src/Native.cpp
     //gcc -shared -fPIC -m64 -o obj/native.o src/Native.cpp
 
-    public static final  boolean  EPOLL_AVAILABLE;
-    public static final  int      EPOLL_ERR;
-    public static final  int      EPOLL_ET;
-    public static final  int      EPOLL_IN;
-    public static final  int      EPOLL_IN_ET;
-    public static final  int      EPOLL_IN_OUT;
-    public static final  int      EPOLL_IN_OUT_ET;
-    public static final  int      EPOLL_OUT;
-    public static final  int      EPOLL_OUT_ET;
-    public static final  int      EPOLL_HUP;
-    public static final  int      EPOLL_RD_HUP;
-    public static final  String[] ERRORS;
-    public static final  boolean  IS_LINUX;
+    public static final int SEEK_SET  = 0;  /* Seek from beginning of file.  */
+    public static final int SEEK_CUR  = 1;  /* Seek from current position.  */
+    public static final int SEEK_END  = 2;  /* Seek from end of file.  */
+    public static final int SEEK_DATA = 3;  /* Seek to next data.  */
+    public static final int SEEK_HOLE = 4;  /* Seek to next hole.  */
+
+    public static final int O_ACCMODE  = 0003;
+    public static final int O_RDONLY   = 00;
+    public static final int O_WRONLY   = 01;
+    public static final int O_RDWR     = 02;
+    public static final int O_CREAT    = 0100;
+    public static final int O_EXCL     = 0200;
+    public static final int O_NOCTTY   = 0400;
+    public static final int O_TRUNC    = 01000;
+    public static final int O_APPEND   = 02000;
+    public static final int O_NONBLOCK = 04000;
+    public static final int O_DIRECT   = 040000;
+    public static final int O_NDELAY   = O_NONBLOCK;
+    public static final int O_SYNC     = 04010000;
+    public static final int O_FSYNC    = O_SYNC;
+    public static final int O_ASYNC    = 020000;
+
+    public static final  int      EPOLL_ERR       = 1 << 3;
+    public static final  int      EPOLL_ET        = 1 << 31;
+    public static final  int      EPOLL_IN        = 1 << 0;
+    public static final  int      EPOLL_OUT       = 1 << 2;
+    public static final  int      EPOLL_HUP       = 1 << 4;
+    public static final  int      EPOLL_RD_HUP    = 1 << 13;
+    public static final  int      EPOLL_IN_ET     = EPOLL_IN | EPOLL_ET;
+    public static final  int      EPOLL_IN_OUT    = EPOLL_IN | EPOLL_OUT;
+    public static final  int      EPOLL_OUT_ET    = EPOLL_OUT | EPOLL_ET;
+    public static final  int      EPOLL_IN_OUT_ET = EPOLL_IN_ET | EPOLL_OUT_ET;
+    public static final  boolean  EPOLL_AVAILABLE = try_load_epoll();
     public static final  int      SIZEOF_EPOLL_EVENT;
     public static final  int      SIZEOF_SOCK_ADDR_IN;
-    private static final Logger   logger = LoggerFactory.getLogger(Native.class);
+    public static final  String[] ERRORS;
+    private static final Logger   logger          = LoggerFactory.getLogger(Native.class);
 
     static {
-        EPOLL_ET = 1 << 31;
-        EPOLL_IN = 1 << 0;
-        EPOLL_OUT = 1 << 2;
-        EPOLL_ERR = 1 << 3;
-        EPOLL_HUP = 1 << 4;
-        EPOLL_RD_HUP = 1 << 13;
-        EPOLL_IN_OUT = EPOLL_IN | EPOLL_OUT;
-        EPOLL_IN_ET = EPOLL_IN | EPOLL_ET;
-        EPOLL_OUT_ET = EPOLL_OUT | EPOLL_ET;
-        EPOLL_IN_OUT_ET = EPOLL_IN_ET | EPOLL_OUT_ET;
-        IS_LINUX = isLinux();
-        EPOLL_AVAILABLE = IS_LINUX && tryLoadEpoll();
         if (EPOLL_AVAILABLE) {
-            ERRORS = new String[256];
-            byte[] temp = new byte[1024];
-            for (int i = 0; i < ERRORS.length; i++) {
-                int len = strerrno(i, temp);
-                ERRORS[i] = new String(temp, 0, len);
-            }
+            ERRORS = load_errors();
             SIZEOF_EPOLL_EVENT = size_of_epoll_event();
             SIZEOF_SOCK_ADDR_IN = size_of_sockaddr_in();
         } else {
+            ERRORS = null;
             SIZEOF_EPOLL_EVENT = -1;
             SIZEOF_SOCK_ADDR_IN = -1;
-            ERRORS = null;
         }
     }
 
-    private static boolean tryLoadEpoll() {
-        if (Options.isEnableEpoll()) {
+    private static String[] load_errors() {
+        String[] errors = new String[256];
+        byte[]   temp   = new byte[1024];
+        for (int i = 0; i < errors.length; i++) {
+            int len = strerrno(i, temp);
+            errors[i] = new String(temp, 0, len);
+        }
+        return errors;
+    }
+
+    private static boolean try_load_epoll() {
+        if (!Unsafe.DIRECT_BUFFER_AVAILABLE) {
+            return false;
+        }
+        if (Unsafe.IS_LINUX && Options.isEnableEpoll()) {
             boolean epollLoaded = false;
             if (Develop.EPOLL_DEBUG) {
                 logger.info("load epoll from:{}", Develop.EPOLL_PATH);
@@ -76,7 +91,7 @@ private static boolean tryLoadEpoll() {
                 }
             } else {
                 try {
-                    loadNative("native.o");
+                    load_native("native.o");
                     epollLoaded = true;
                 } catch (Throwable e) {
                     if (Develop.NATIVE_DEBUG) {
@@ -92,7 +107,7 @@ private static boolean tryLoadEpoll() {
                         return true;
                     }
                     if (Develop.NATIVE_DEBUG) {
-                        logger.error("epoll creat failed:" + Native.err_str());
+                        logger.error("epoll create failed:" + Native.err_str());
                     }
                 } catch (Throwable e) {
                 }
@@ -101,12 +116,20 @@ private static boolean tryLoadEpoll() {
         return false;
     }
 
+    private static void load_native(String name) throws IOException {
+        byte[] native_data = FileUtil.readBytesByCls(name, Native.class.getClassLoader());
+        File   native_tmp  = File.createTempFile(name, ".o");
+        FileUtil.writeByFile(native_tmp, native_data);
+        System.load(native_tmp.getAbsolutePath());
+        native_tmp.deleteOnExit();
+    }
+
     public static int close_event() {
         return EPOLL_ERR | EPOLL_HUP | EPOLL_RD_HUP;
     }
 
     public static int accept(int epfd, int listen_fd, long address) {
-        return printException(accept0(epfd, listen_fd, address));
+        return print_exception(accept0(epfd, listen_fd, address));
     }
 
     public static int bind(String host, int port, int backlog) {
@@ -117,11 +140,11 @@ public static int close(int fd) {
         if (fd == -1) {
             return -1;
         }
-        return printException(close0(fd));
+        return print_exception(close0(fd));
     }
 
     public static int connect(String host, int port) {
-        return printException(connect0(host, port));
+        return print_exception(connect0(host, port));
     }
 
     public static int epoll_add(int epfd, int fd, int state) {
@@ -136,19 +159,17 @@ public static int epoll_del(int epfd, int fd) {
         if (fd == -1) {
             return -1;
         }
-        return printException(epoll_del0(epfd, fd));
+        return print_exception(epoll_del0(epfd, fd));
     }
 
     public static int epoll_mod(int epfd, int fd, int state) {
-        return printException(epoll_mod0(epfd, fd, state));
+        return print_exception(epoll_mod0(epfd, fd, state));
     }
 
-    public static int epoll_wait(int fd, long address, int maxEvents, long timeout) {
-        return printException(epoll_wait0(fd, address, maxEvents, timeout));
+    public static int epoll_wait(int fd, long address, int max_events, long timeout) {
+        return print_exception(epoll_wait0(fd, address, max_events, timeout));
     }
 
-    public static native int errno();
-
     public static String err_str() {
         return err_str(errno());
     }
@@ -162,24 +183,11 @@ private static String err_str(int errno) {
     }
 
     public static int event_fd_read(int fd) {
-        return printException(event_fd_read0(fd));
+        return print_exception(event_fd_read0(fd));
     }
 
     public static int event_fd_write(int fd, long value) {
-        return printException(event_fd_write0(fd, value));
-    }
-
-    private static boolean isLinux() {
-        return Util.getStringProperty("os.name", "").toLowerCase().startsWith("lin");
-    }
-
-    private static void loadNative(String name) throws IOException {
-        InputStream in      = Native.class.getClassLoader().getResourceAsStream(name);
-        File        tmpFile = File.createTempFile(name, ".o");
-        byte[]      data    = FileUtil.inputStream2ByteArray(in);
-        FileUtil.writeByFile(tmpFile, data);
-        System.load(tmpFile.getAbsolutePath());
-        tmpFile.deleteOnExit();
+        return print_exception(event_fd_write0(fd, value));
     }
 
     public static long new_epoll_event_array(int size) {
@@ -191,10 +199,14 @@ public static int new_event_fd() {
     }
 
     public static int read(int fd, long address, int len) {
-        return printException(read0(fd, address, len));
+        return print_exception(read0(fd, address, len));
     }
 
-    private static int printException(int res) {
+    public static int pread(int fd, long address, int len, long pos) {
+        return print_exception(pread0(fd, address, len, pos));
+    }
+
+    private static int print_exception(int res) {
         if (Develop.NATIVE_DEBUG && res == -1) {
             int errno = errno();
             if (errno != 0) {
@@ -205,11 +217,16 @@ private static int printException(int res) {
         return res;
     }
 
-    public static native int size_of_epoll_event();
-
-    public static native int size_of_sockaddr_in();
-
-    public static native int strerrno(int no, byte[] buf);
+    private static long print_exception(long res) {
+        if (Develop.NATIVE_DEBUG && res == -1) {
+            int errno = errno();
+            if (errno != 0) {
+                IOException e = new IOException(err_str(errno));
+                logger.error(e.getMessage(), e);
+            }
+        }
+        return res;
+    }
 
     public static int throwException(int res) throws IOException {
         if (res == -1) {
@@ -226,30 +243,39 @@ public static int throwRuntimeException(int res) {
     }
 
     public static int write(int fd, long address, int len) {
-        return printException(write0(fd, address, len));
+        return print_exception(write0(fd, address, len));
+    }
+
+    public static int pwrite(int fd, long address, int len, long pos) {
+        return print_exception(pwrite0(fd, address, len, pos));
     }
 
     public static int get_port(int fd) {
-        return Short.reverseBytes((short) printException(get_port0(fd))) & 0xffff;
+        return Short.reverseBytes((short) print_exception(get_port0(fd))) & 0xffff;
     }
 
     public static long writev(int fd, long iovec, int count) {
-        return printException(writev0(fd, iovec, count));
+        return print_exception(writev0(fd, iovec, count));
     }
 
     public static int set_socket_opt(int fd, int type, int name, int value) {
-        return printException(set_socket_opt0(fd, type, name, value));
+        return print_exception(set_socket_opt0(fd, type, name, value));
     }
 
     public static boolean finish_connect(int fd) {
-        int type = SocketOptions.SOL_SOCKET >> 16;
+        int type = SocketOptions.RAW_SOL_SOCKET;
         int res  = get_socket_opt0(fd, type, SocketOptions.SO_ERROR & 0xff);
         if (res != 0) {
             if (res == -1) {
-                printException(res);
+                print_exception(res);
             } else {
-                IOException e = new IOException(err_str(res & 0x7fffffff));
-                logger.error(e.getMessage(), e);
+                if (Develop.NATIVE_DEBUG) {
+                    if (res < 0) {
+                        res = -res;
+                    }
+                    IOException e = new IOException(err_str(res));
+                    logger.error(e.getMessage(), e);
+                }
             }
             return false;
         }
@@ -257,10 +283,35 @@ public static boolean finish_connect(int fd) {
     }
 
     public static int get_socket_opt(int fd, int type, int name) {
-        return printException(get_socket_opt0(fd, type, name));
+        return print_exception(get_socket_opt0(fd, type, name));
+    }
+
+    public static int open(String path, int op, int pem) {
+        return print_exception(open0(path, op, pem));
+    }
+
+    public static long posix_memalign_allocate(int len, int align) {
+        return print_exception(posix_memalign_allocate0(len, align));
+    }
+
+    public static long file_length(int fd) {
+        return print_exception(file_length0(fd));
+    }
+
+    public static long lseek(int fd, long off, int seek_mode) {
+        return print_exception(lseek0(fd, off, seek_mode));
     }
 
-    //---------------------------------------------------------------------------------------------------------
+    // epoll----------------------------------------------------------------------------------------
+
+    public static native int errno();
+
+    private static native int size_of_epoll_event();
+
+    private static native int size_of_sockaddr_in();
+
+    private static native int strerrno(int no, byte[] buf);
+
     private static native int get_socket_opt0(int fd, int type, int name);
 
     private static native int set_socket_opt0(int fd, int type, int name, int value);
@@ -281,7 +332,7 @@ public static int get_socket_opt(int fd, int type, int name) {
 
     private static native int epoll_mod0(int epfd, int fd, int state);
 
-    private static native int epoll_wait0(int fd, long address, int maxEvents, long timeout);
+    private static native int epoll_wait0(int fd, long address, int max_events, long timeout);
 
     private static native int event_fd_read0(int fd);
 
@@ -297,4 +348,18 @@ public static int get_socket_opt(int fd, int type, int name) {
 
     private static native int writev0(int fd, long iovec, int count);
 
+    // direct io----------------------------------------------------------------------------------------
+
+    private static native int open0(String path, int op, int pem);
+
+    private static native long posix_memalign_allocate0(int len, int align);
+
+    private static native long file_length0(int fd);
+
+    private static native long lseek0(int fd, long off, int seek_mode);
+
+    private static native int pread0(int fd, long address, int len, long off);
+
+    private static native int pwrite0(int fd, long address, int len, long off);
+
 }
diff --git a/firenio-core/src/main/java/com/firenio/component/NioEventLoop.java b/firenio-core/src/main/java/com/firenio/component/NioEventLoop.java
index 6dc7a0200..4c2dd2083 100644
--- a/firenio-core/src/main/java/com/firenio/component/NioEventLoop.java
+++ b/firenio-core/src/main/java/com/firenio/component/NioEventLoop.java
@@ -29,10 +29,8 @@
 import java.security.PrivilegedAction;
 import java.util.AbstractSet;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
@@ -43,8 +41,11 @@
 import com.firenio.buffer.ByteBuf;
 import com.firenio.buffer.ByteBufAllocator;
 import com.firenio.collection.ArrayListStack;
-import com.firenio.collection.Attributes;
+import com.firenio.collection.AttributeKey;
+import com.firenio.collection.AttributeMap;
+import com.firenio.collection.AttributeMap.AttributeInitFunction;
 import com.firenio.collection.DelayedQueue;
+import com.firenio.collection.IntArray;
 import com.firenio.collection.IntMap;
 import com.firenio.collection.LinkedBQStack;
 import com.firenio.collection.Stack;
@@ -64,28 +65,33 @@
 /**
  * @author wangkai
  */
-public abstract class NioEventLoop extends EventLoop implements Attributes {
+public abstract class NioEventLoop extends EventLoop {
 
     static final boolean     CHANNEL_READ_FIRST = Options.isChannelReadFirst();
     static final Logger      logger             = NEW_LOGGER();
     static final IOException NOT_FINISH_CONNECT = NOT_FINISH_CONNECT();
     static final IOException OVER_CH_SIZE_LIMIT = OVER_CH_SIZE_LIMIT();
+    // NOTICE USE_HAS_TASK can make a memory barrier for io thread,
+    // please do not change this value to false unless you are really need.
+    // I am not sure if the select()/select(n) has memory barrier,
+    // it can be set USE_HAS_TASK to false if there is a memory barrier.
     static final boolean     USE_HAS_TASK       = true;
 
     final    ByteBufAllocator        alloc;
-    final    Map     attributes    = new HashMap<>();
     final    ByteBuf                 buf;
-    final    IntMap         channels      = new IntMap<>(4096);
+    final    AttributeMap            attributeMap   = new NioEventLoopAttributeMap();
+    final    IntMap         channels       = new IntMap<>(4096);
+    final    IntArray                close_channels = new IntArray();
     final    int                     ch_size_limit;
-    final    DelayedQueue            delayed_queue = new DelayedQueue();
-    final    BlockingQueue events        = new LinkedBlockingQueue<>();
+    final    DelayedQueue            delayed_queue  = new DelayedQueue();
+    final    BlockingQueue events         = new LinkedBlockingQueue<>();
     final    NioEventLoopGroup       group;
     final    int                     index;
-    final    AtomicInteger           selecting     = new AtomicInteger();
+    final    AtomicInteger           selecting      = new AtomicInteger();
     final    boolean                 sharable;
     final    long                    buf_address;
     final    boolean                 acceptor;
-    volatile boolean                 has_task      = false;
+    volatile boolean                 has_task       = false;
 
     NioEventLoop(NioEventLoopGroup group, int index, String threadName) {
         super(threadName);
@@ -97,43 +103,43 @@ public abstract class NioEventLoop extends EventLoop implements Attributes {
         this.ch_size_limit = group.getChannelSizeLimit();
         int channelReadBuffer = group.getChannelReadBuffer();
         if (channelReadBuffer > 0) {
-            this.buf = ByteBuf.direct(channelReadBuffer);
-            this.buf_address = Unsafe.address(buf.getNioBuffer());
+            this.buf = ByteBuf.buffer(channelReadBuffer);
+            this.buf_address = buf.address();
         } else {
             this.buf = null;
             this.buf_address = -1;
         }
     }
 
-    private static void channel_idle(ChannelIdleListener l, Channel ch, long lastIdleTime, long currentTime) {
+    private static void channel_idle(ChannelIdleListener l, Channel ch, long lastIdleTime) {
         try {
-            l.channelIdled(ch, lastIdleTime, currentTime);
-        } catch (Exception e) {
+            l.channelIdled(ch, lastIdleTime);
+        } catch (Throwable e) {
             logger.error(e.getMessage(), e);
         }
     }
 
-    private static void channel_idle(ChannelContext context, IntMap channels, long last_idle_time, long current_time) {
+    private static void channel_idle(ChannelContext context, IntMap channels, long last_idle_time) {
         List ls = context.getChannelIdleEventListeners();
         for (int i = 0; i < ls.size(); i++) {
             ChannelIdleListener l = ls.get(i);
             for (channels.scan(); channels.hasNext(); ) {
-                Channel ch = channels.nextValue();
-                channel_idle(l, ch, last_idle_time, current_time);
+                Channel ch = channels.value();
+                channel_idle(l, ch, last_idle_time);
             }
         }
     }
 
-    private static void channel_idle_share(IntMap channels, long last_idle_time, long current_time) {
+    private static void channel_idle_share(IntMap channels, long last_idle_time) {
         for (channels.scan(); channels.hasNext(); ) {
-            Channel                   ch      = channels.nextValue();
+            Channel                   ch      = channels.value();
             ChannelContext            context = ch.getContext();
             List ls      = context.getChannelIdleEventListeners();
             if (ls.size() == 1) {
-                channel_idle(ls.get(0), ch, last_idle_time, current_time);
+                channel_idle(ls.get(0), ch, last_idle_time);
             } else {
                 for (int i = 0; i < ls.size(); i++) {
-                    channel_idle(ls.get(i), ch, last_idle_time, current_time);
+                    channel_idle(ls.get(i), ch, last_idle_time);
                 }
             }
         }
@@ -163,7 +169,7 @@ static IOException NOT_FINISH_CONNECT() {
     }
 
     static IOException OVER_CH_SIZE_LIMIT() {
-        return Util.unknownStackTrace(new IOException("over channel size limit"), NioEventLoop.class, "register_channel(...)");
+        return Util.unknownStackTrace(new IOException("over channel size writeIndex"), NioEventLoop.class, "register_channel(...)");
     }
 
     static void read_exception_caught(Channel ch, Throwable ex) {
@@ -178,32 +184,23 @@ public ByteBufAllocator alloc() {
         return alloc;
     }
 
-    @Override
-    public Map attributes() {
-        return attributes;
-    }
-
     //FIXME ..optimize sharable group
-    private void channel_idle(long last_idle_time, long current_time) {
+    private void channel_idle(long last_idle_time) {
         IntMap channels = this.channels;
         if (channels.isEmpty()) {
             return;
         }
         if (sharable) {
-            channel_idle_share(channels, last_idle_time, current_time);
+            channel_idle_share(channels, last_idle_time);
         } else {
-            channel_idle(group.getContext(), channels, last_idle_time, current_time);
+            channel_idle(group.getContext(), channels, last_idle_time);
         }
     }
 
-    @Override
-    public void clearAttributes() {
-        this.attributes.clear();
-    }
-
     private void close_channels() {
+        IntMap channels = this.channels;
         for (channels.scan(); channels.hasNext(); ) {
-            Util.close(channels.nextValue());
+            Util.close(channels.value());
         }
     }
 
@@ -211,23 +208,16 @@ protected long getBufAddress() {
         return buf_address;
     }
 
-    @Override
-    public Object getAttribute(Object key) {
-        return this.attributes.get(key);
-    }
-
-    @Override
-    public Set getAttributeNames() {
-        return this.attributes.keySet();
+    public  T getAttribute(AttributeKey key) {
+        return attributeMap.getAttribute(key);
     }
 
     public Channel getChannel(int channelId) {
         return channels.get(channelId);
     }
 
-    @SuppressWarnings("unchecked")
-    private Stack get_cache0(String key, int max) {
-        Stack cache = (Stack) getAttribute(key);
+    private Stack get_cache0(AttributeKey> key, int max) {
+        Stack cache = getAttribute(key);
         if (cache == null) {
             if (group.isConcurrentFrameStack()) {
                 cache = new LinkedBQStack<>(max);
@@ -239,7 +229,7 @@ private Stack get_cache0(String key, int max) {
         return cache;
     }
 
-    public Object getCache(String key, int max) {
+    public Object getCache(AttributeKey> key, int max) {
         return get_cache0(key, max).pop();
     }
 
@@ -261,21 +251,19 @@ protected ByteBuf getReadBuf() {
         return buf;
     }
 
-    @SuppressWarnings("unchecked")
-    public void release(String key, Object obj) {
-        Stack buffer = (Stack) getAttribute(key);
+    public void release(AttributeKey> key, Object obj) {
+        Stack buffer = getAttribute(key);
         if (buffer != null) {
             buffer.push(obj);
         }
     }
 
-    @Override
-    public Object removeAttribute(Object key) {
-        return this.attributes.remove(key);
+    public AttributeMap getAttributeMap() {
+        return attributeMap;
     }
 
     protected void removeChannel(int id) {
-        channels.remove(id);
+        close_channels.add(id);
     }
 
     private void run_events(BlockingQueue events) {
@@ -329,11 +317,12 @@ private void clear_has_task() {
         }
     }
 
-    private long run_delayed_events(DelayedQueue dq, long now, long nextIdle, long selectTime) {
+    private long run_delayed_events(DelayedQueue dq, long nextIdle) {
+        long now = Util.now();
         for (; ; ) {
             DelayedQueue.DelayTask t = dq.peek();
             if (t == null) {
-                break;
+                return nextIdle - now;
             }
             if (t.isCanceled()) {
                 dq.poll();
@@ -348,15 +337,15 @@ private long run_delayed_events(DelayedQueue dq, long now, long nextIdle, long s
                 } catch (Throwable e) {
                     logger.error(e.getMessage(), e);
                 }
-                continue;
-            }
-            if (delay < nextIdle) {
-                return delay - now;
+                now = Util.now();
             } else {
-                return selectTime;
+                if (delay < nextIdle) {
+                    return delay - now;
+                } else {
+                    return nextIdle - now;
+                }
             }
         }
-        return selectTime;
     }
 
     @Override
@@ -366,8 +355,8 @@ public void run() {
         final AtomicInteger           selecting      = this.selecting;
         final BlockingQueue events         = this.events;
         final DelayedQueue            dq             = this.delayed_queue;
-        long                          next_idle_time = 0;
-        long                          last_idle_time = 0;
+        long                          last_idle_time = Util.now();
+        long                          next_idle_time = last_idle_time + idle;
         long                          select_time    = idle;
         for (; ; ) {
             // when this event loop is going to shutdown,we do not handle the last events
@@ -401,23 +390,37 @@ public void run() {
                 }
                 long now = Util.now();
                 if (now >= next_idle_time) {
-                    channel_idle(last_idle_time, now);
-                    last_idle_time = now;
-                    next_idle_time = now + idle;
-                    select_time = idle;
-                } else {
-                    select_time = next_idle_time - now;
+                    channel_idle(last_idle_time);
+                    last_idle_time = next_idle_time;
+                    next_idle_time = next_idle_time + idle;
                 }
                 run_events(events);
                 if (!dq.isEmpty()) {
-                    select_time = run_delayed_events(dq, now, next_idle_time, select_time);
+                    select_time = run_delayed_events(dq, next_idle_time);
+                } else {
+                    select_time = next_idle_time - Util.now();
                 }
+                remove_closed_channels();
             } catch (Throwable e) {
                 logger.error(e);
             }
         }
     }
 
+    private void remove_closed_channels() {
+        IntArray        c_list   = this.close_channels;
+        IntMap channels = this.channels;
+        if (!c_list.isEmpty()) {
+            for (int i = 0; i < c_list.size(); i++) {
+                Channel ch = channels.remove(c_list.get(i));
+                if (ch.isOpen()) {
+                    channels.put(ch.getChannelId(), ch);
+                }
+            }
+            c_list.clear();
+        }
+    }
+
     public boolean schedule(final DelayedQueue.DelayTask task) {
         if (inEventLoop()) {
             return delayed_queue.offer(task);
@@ -432,9 +435,8 @@ public void run() {
         }
     }
 
-    @Override
-    public void setAttribute(Object key, Object value) {
-        this.attributes.put(key, value);
+    public void setAttribute(AttributeKey key, Object value) {
+        this.attributeMap.setAttribute(key, value);
     }
 
     public boolean submit(Runnable event) {
@@ -473,6 +475,13 @@ public void wakeup() {
 
     abstract void wakeup0();
 
+    public static AttributeKey valueOfKey(String name) {
+        return AttributeMap.valueOfKey(NioEventLoop.class, name);
+    }
+
+    public static AttributeKey valueOfKey(String name, AttributeInitFunction function) {
+        return AttributeMap.valueOfKey(NioEventLoop.class, name, function);
+    }
 
     static final class JavaEventLoop extends NioEventLoop {
 
@@ -539,7 +548,7 @@ public Object run() {
                         selectedKeysField.set(selector, keySet);
                         publicSelectedKeysField.set(selector, keySet);
                         return null;
-                    } catch (Exception e) {
+                    } catch (Throwable e) {
                         return e;
                     }
                 }
@@ -626,7 +635,7 @@ private void accept(final ChannelAcceptor acceptor) {
                     public void run() {
                         try {
                             register_channel(ch, targetEL, acceptor, true);
-                        } catch (IOException e) {
+                        } catch (Throwable e) {
                             logger.error(e.getMessage(), e);
                         }
                     }
@@ -724,7 +733,7 @@ private void register_channel(SocketChannel jch, NioEventLoop el, ChannelContext
         int select(long timeout) {
             try {
                 return selector.select(timeout);
-            } catch (IOException e) {
+            } catch (Throwable e) {
                 debugException(logger, e);
                 return 0;
             }
@@ -734,7 +743,7 @@ int select(long timeout) {
         int select_now() {
             try {
                 return selector.selectNow();
-            } catch (IOException e) {
+            } catch (Throwable e) {
                 debugException(logger, e);
                 return 0;
             }
@@ -917,8 +926,11 @@ public void run() {
         private void accept(int fd, int e) {
             Channel ch = getChannel(fd);
             if (ch != null) {
-                if (!ch.isOpen()) {
-                    return;
+                if (Develop.CHANNEL_DEBUG) {
+                    if (!ch.isOpen()) {
+                        logger.error("channel closed but goto accept block");
+                        return;
+                    }
                 }
                 if ((e & Native.close_event()) != 0) {
                     ch.close();
@@ -961,6 +973,12 @@ private void accept(int fd, int e) {
 
         private void accept_connect(int fd, int e) {
             ChannelConnector ctx = (ChannelConnector) ctxs.remove(fd);
+            if (ctx == null) {
+                if (Develop.CHANNEL_DEBUG) {
+                    logger.error("server run in accept_connect........");
+                }
+                return;
+            }
             if ((e & Native.close_event()) != 0 || !Native.finish_connect(fd)) {
                 ctx.channelEstablish(null, NOT_FINISH_CONNECT);
                 return;
@@ -1011,8 +1029,8 @@ private void register_channel(NioEventLoop el, ChannelContext ctx, int fd, Strin
             }
             Channel old = channels.get(fd);
             if (old != null) {
-                if (Develop.NATIVE_DEBUG) {
-                    logger.error("old channel ....................,open:{}", old.isOpen());
+                if (Develop.CHANNEL_DEBUG) {
+                    logger.error("old channel ....................,{},open:{}", old, old.isOpen());
                 }
                 old.close();
             }
@@ -1037,4 +1055,13 @@ void wakeup0() {
 
     }
 
+    static class NioEventLoopAttributeMap extends AttributeMap {
+
+        @Override
+        protected AttributeKeys getKeys() {
+            return getKeys(NioEventLoop.class);
+        }
+
+    }
+
 }
diff --git a/firenio-core/src/main/java/com/firenio/component/NioEventLoopGroup.java b/firenio-core/src/main/java/com/firenio/component/NioEventLoopGroup.java
index af4f8cb3b..9c0f76a42 100644
--- a/firenio-core/src/main/java/com/firenio/component/NioEventLoopGroup.java
+++ b/firenio-core/src/main/java/com/firenio/component/NioEventLoopGroup.java
@@ -20,6 +20,7 @@
 import com.firenio.buffer.ByteBufAllocator;
 import com.firenio.buffer.ByteBufAllocatorGroup;
 import com.firenio.buffer.UnpooledByteBufAllocator;
+import com.firenio.common.Unsafe;
 import com.firenio.common.Util;
 import com.firenio.component.NioEventLoop.EpollEventLoop;
 import com.firenio.component.NioEventLoop.JavaEventLoop;
@@ -42,7 +43,7 @@ public class NioEventLoopGroup extends EventLoopGroup {
     private       ChannelContext        context;
     private       boolean               enableMemoryPool       = true;
     //内存池是否使用启用堆外内存
-    private       boolean               enableMemoryPoolDirect = true;
+    private       boolean               enableMemoryPoolDirect = Unsafe.DIRECT_BUFFER_AVAILABLE;
     private       NioEventLoop[]        eventLoops;
     private       long                  idleTime               = 30 * 1000;
     //内存池内存单元数量(单核)
@@ -102,6 +103,15 @@ protected void doStart() throws Exception {
             memoryPoolCapacity = (int) (total / (memoryPoolUnit * getEventLoopSize() * memoryPoolRate));
         }
         if (isEnableMemoryPool() && getAllocatorGroup() == null) {
+            if (Native.EPOLL_AVAILABLE) {
+                if (!isEnableMemoryPoolDirect()) {
+                    throw new Exception("EPoll mode only support unsafe(direct) memory");
+                }
+            } else {
+                if (Unsafe.UNSAFE_BUF_AVAILABLE) {
+                    throw new Exception("Java(Nio) mode can not use unsafe memory");
+                }
+            }
             this.allocatorGroup = new ByteBufAllocatorGroup(getEventLoopSize(), memoryPoolCapacity, memoryPoolUnit, enableMemoryPoolDirect);
         }
         Util.start(getAllocatorGroup());
@@ -197,7 +207,7 @@ public NioEventLoop getNext() {
     public ByteBufAllocator getNextByteBufAllocator(int index) {
         ByteBufAllocatorGroup group = allocatorGroup;
         if (group == null) {
-            return UnpooledByteBufAllocator.get(isEnableMemoryPoolDirect());
+            return UnpooledByteBufAllocator.get();
         } else {
             return group.getAllocator(index);
         }
@@ -209,6 +219,9 @@ public int getWriteBuffers() {
 
     public void setWriteBuffers(int writeBuffers) {
         checkNotRunning();
+        if (writeBuffers > Byte.MAX_VALUE) {
+            throw new RuntimeException("max write buffer size: " + Byte.MAX_VALUE);
+        }
         this.writeBuffers = writeBuffers;
     }
 
diff --git a/firenio-core/src/main/java/com/firenio/component/ProtocolCodec.java b/firenio-core/src/main/java/com/firenio/component/ProtocolCodec.java
index d1a274359..c1ff8478a 100644
--- a/firenio-core/src/main/java/com/firenio/component/ProtocolCodec.java
+++ b/firenio-core/src/main/java/com/firenio/component/ProtocolCodec.java
@@ -59,16 +59,14 @@ protected static IOException EXCEPTION(String method, String msg) {
         return EXCEPTION(clazz, method, msg);
     }
 
-    protected static int nextIndexedVariablesIndex() {
-        return FastThreadLocal.nextIndexedVariablesIndex();
-    }
-
     // 可能会遭受一种攻击,比如最大可接收数据为100,客户端传输到99后暂停,
     // 这样多次以后可能会导致内存溢出
     public abstract Frame decode(Channel ch, ByteBuf src) throws Exception;
 
     // 注意:encode失败要release掉encode过程中申请的内存
-    public abstract ByteBuf encode(Channel ch, Frame frame) throws Exception;
+    public ByteBuf encode(Channel ch, Frame frame) throws Exception {
+        throw new UnsupportedOperationException();
+    }
 
     public abstract String getProtocolId();
 
@@ -103,6 +101,19 @@ protected void flush_pong(Channel ch, ByteBuf buf) {
         ch.getContext().getHeartBeatLogger().logPongTo(ch);
     }
 
+    protected ByteBuf getPlainReadBuf(NioEventLoop el, Channel ch) {
+        return el.getReadBuf();
+    }
+
+    protected void storePlainReadRemain(Channel ch, ByteBuf src) {
+        ch.slice_remain_plain(src);
+    }
+
+    protected void readPlainRemain(Channel ch, ByteBuf dst) {
+        dst.clear();
+        ch.read_plain_remain(dst);
+    }
+
     protected ByteBuf getPingBuf() {
         return null;
     }
diff --git a/firenio-core/src/main/java/com/firenio/component/ReConnector.java b/firenio-core/src/main/java/com/firenio/component/ReConnector.java
index 041f490d5..c3a70b708 100644
--- a/firenio-core/src/main/java/com/firenio/component/ReConnector.java
+++ b/firenio-core/src/main/java/com/firenio/component/ReConnector.java
@@ -27,6 +27,7 @@ public class ReConnector implements Closeable {
     private          Logger           logger    = LoggerFactory.getLogger(getClass());
     private volatile boolean          reconnect = true;
     private          long             retryTime = 15000;
+    private          long             timeout   = 3000;
 
     public ReConnector(ChannelConnector connector) {
         this.connector = connector;
@@ -38,9 +39,20 @@ public synchronized void close() {
         this.reconnect = false;
         Util.close(connector);
         Util.stop(connector.getProcessorGroup());
+        this.notify();
     }
 
     public synchronized void connect() {
+        connect(3000);
+    }
+
+    public synchronized void connect(long timeout) {
+        this.reconnect = true;
+        this.timeout = timeout;
+        this.connect0();
+    }
+
+    public synchronized void connect0() {
         Channel ch = connector.getChannel();
         for (; ; ) {
             if (ch != null && ch.isOpen()) {
@@ -52,13 +64,17 @@ public synchronized void connect() {
             }
             logger.info("begin try to connect");
             try {
-                connector.connect();
+                connector.connect(timeout);
                 break;
             } catch (Throwable e) {
                 logger.error(e.getMessage(), e);
             }
             logger.error("reconnect failed,try reconnect later on {} milliseconds", retryTime);
-            Util.sleep(retryTime);
+            try {
+                this.wait(retryTime);
+            } catch (InterruptedException e) {
+                logger.error(e.getMessage(), e);
+            }
         }
     }
 
@@ -87,7 +103,7 @@ public void channelClosed(Channel ch) {
                 Util.exec(new Runnable() {
                     @Override
                     public void run() {
-                        reConnector.connect();
+                        reConnector.connect0();
                     }
                 });
             }
diff --git a/firenio-core/src/main/java/com/firenio/component/SilentExceptionCaughtHandle.java b/firenio-core/src/main/java/com/firenio/component/SilentExceptionCaughtHandle.java
index c55469557..20ee7bbde 100644
--- a/firenio-core/src/main/java/com/firenio/component/SilentExceptionCaughtHandle.java
+++ b/firenio-core/src/main/java/com/firenio/component/SilentExceptionCaughtHandle.java
@@ -21,6 +21,6 @@
 public class SilentExceptionCaughtHandle implements ExceptionCaughtHandle {
 
     @Override
-    public void exceptionCaught(Channel ch, Frame frame, Exception ex) {}
+    public void exceptionCaught(Channel ch, Frame frame, Throwable ex) {}
 
 }
diff --git a/firenio-core/src/main/java/com/firenio/component/SocketOptions.java b/firenio-core/src/main/java/com/firenio/component/SocketOptions.java
index 1704a076f..700ff984b 100644
--- a/firenio-core/src/main/java/com/firenio/component/SocketOptions.java
+++ b/firenio-core/src/main/java/com/firenio/component/SocketOptions.java
@@ -23,24 +23,26 @@
  */
 public final class SocketOptions {
 
-    public static final  int      PARAM_BOOLEAN;
-    public static final  int      IPPROTO_TCP;
-    public static final  int      SOL_SOCKET;
-    public static final  int      SO_BROADCAST;
-    public static final  int      SO_ERROR;
-    public static final  int      SO_KEEPALIVE;
-    public static final  int      SO_SNDBUF;
-    public static final  int      SO_RCVBUF;
-    public static final  int      SO_REUSEADDR;
-    public static final  int      SO_LINGER;
-    public static final  int      TCP_NODELAY;
-    public static final  int      TCP_QUICKACK;
-    private static final Object[] TCP_SOCKET_OPTIONS = new Object[16];
-    private static final Object[] SO_SOCKET_OPTIONS  = new Object[16];
+    public static final int      RAW_IP_PROTO_TCP   = 6;
+    public static final int      RAW_SOL_SOCKET     = 1;
+    public static final int      SOL_SOCKET;
+    public static final int      SO_BROADCAST;
+    public static final int      SO_ERROR;
+    public static final int      SO_KEEPALIVE;
+    public static final int      SO_SNDBUF;
+    public static final int      SO_RCVBUF;
+    public static final int      SO_REUSEADDR;
+    public static final int      SO_LINGER;
+    public static final int      TCP_NODELAY;
+    public static final int      TCP_QUICKACK;
+    static final        int      PARAM_BOOLEAN;
+    static final        int      IP_PROTO_TCP;
+    static final        Object[] TCP_SOCKET_OPTIONS = new Object[16];
+    static final        Object[] SO_SOCKET_OPTIONS  = new Object[16];
 
     static {
-        IPPROTO_TCP = 6 << 16;
-        SOL_SOCKET = 1 << 16;
+        IP_PROTO_TCP = RAW_IP_PROTO_TCP << 16;
+        SOL_SOCKET = RAW_SOL_SOCKET << 16;
         PARAM_BOOLEAN = 1 << 8;
         SO_ERROR = SOL_SOCKET | 4;
         SO_BROADCAST = SOL_SOCKET | PARAM_BOOLEAN | 6;
@@ -49,8 +51,8 @@ public final class SocketOptions {
         SO_RCVBUF = SOL_SOCKET | 8;
         SO_REUSEADDR = SOL_SOCKET | PARAM_BOOLEAN | 2;
         SO_LINGER = SOL_SOCKET | 13;
-        TCP_NODELAY = IPPROTO_TCP | PARAM_BOOLEAN | 1;
-        TCP_QUICKACK = IPPROTO_TCP | PARAM_BOOLEAN | 12;
+        TCP_NODELAY = IP_PROTO_TCP | PARAM_BOOLEAN | 1;
+        TCP_QUICKACK = IP_PROTO_TCP | PARAM_BOOLEAN | 12;
         TCP_SOCKET_OPTIONS[TCP_NODELAY & 0xff] = StandardSocketOptions.TCP_NODELAY;
         SO_SOCKET_OPTIONS[SO_BROADCAST & 0xff] = StandardSocketOptions.SO_BROADCAST;
         SO_SOCKET_OPTIONS[SO_KEEPALIVE & 0xff] = StandardSocketOptions.SO_KEEPALIVE;
@@ -62,7 +64,7 @@ public final class SocketOptions {
 
     @SuppressWarnings("unchecked")
     public static SocketOption getSocketOption(int name) {
-        if ((name & IPPROTO_TCP) != 0) {
+        if ((name & IP_PROTO_TCP) != 0) {
             return (SocketOption) TCP_SOCKET_OPTIONS[name & 0xff];
         } else if ((name & SOL_SOCKET) != 0) {
             return (SocketOption) SO_SOCKET_OPTIONS[name & 0xff];
diff --git a/firenio-core/src/main/java/com/firenio/component/SslContext.java b/firenio-core/src/main/java/com/firenio/component/SslContext.java
index 015049741..164f3d56f 100644
--- a/firenio-core/src/main/java/com/firenio/component/SslContext.java
+++ b/firenio-core/src/main/java/com/firenio/component/SslContext.java
@@ -31,18 +31,20 @@
 import javax.net.ssl.SSLSessionContext;
 
 import com.firenio.Options;
+import com.firenio.common.Unsafe;
 import com.firenio.log.Logger;
 import com.firenio.log.LoggerFactory;
 
 //ref from netty && undertow
 public final class SslContext {
 
-    public static final List ENABLED_CIPHERS;
-    public static final String[]     ENABLED_PROTOCOLS;
+    public static final List DEFAULT_CIPHERS;
+    public static final List DEFAULT_PROTOCOLS;
     public static final boolean      OPENSSL_AVAILABLE;
     public static final int          SSL_PACKET_BUFFER_SIZE;
     public static final int          SSL_UNWRAP_BUFFER_SIZE;
     public static final Set  SUPPORTED_CIPHERS;
+    public static final Set  SUPPORTED_PROTOCOLS;
     static final        Logger       logger = LoggerFactory.getLogger(SslContext.class);
 
     static {
@@ -53,12 +55,12 @@ public final class SslContext {
         }
         boolean testOpenSsl = false;
         try {
-            if (Options.isEnableOpenssl()) {
+            if (Options.isEnableOpenssl() && Unsafe.UNSAFE_AVAILABLE) {
                 Class.forName("org.wildfly.openssl.OpenSSLProvider");
                 org.wildfly.openssl.OpenSSLProvider.register();
                 testOpenSsl = true;
             }
-        } catch (Exception | Error e) {
+        } catch (Throwable e) {
         }
         OPENSSL_AVAILABLE = testOpenSsl;
         SSLContext context;
@@ -68,64 +70,61 @@ public final class SslContext {
         } catch (Exception e) {
             throw new Error("failed to initialize the default SSL context", e);
         }
-        SSL_UNWRAP_BUFFER_SIZE = Options.getSslUnwrapBufferSize(1024 * 256);
         SSLEngine engine = context.createSSLEngine();
+        SSL_UNWRAP_BUFFER_SIZE = Options.getSslUnwrapBufferSize(1024 * 256);
         SSL_PACKET_BUFFER_SIZE = engine.getSession().getPacketBufferSize();
+
         // Choose the sensible default list of protocols.
-        final String[] supportedProtocols    = engine.getSupportedProtocols();
-        Set    supportedProtocolsSet = new HashSet<>(supportedProtocols.length);
-        supportedProtocolsSet.addAll(Arrays.asList(supportedProtocols));
-        List protocols = new ArrayList<>();
-        addIfSupported(supportedProtocolsSet, protocols, "TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1");
-        if (!protocols.isEmpty()) {
-            ENABLED_PROTOCOLS = protocols.toArray(new String[0]);
-        } else {
-            ENABLED_PROTOCOLS = engine.getEnabledProtocols();
-        }
+        final String[] supportedProtocols = engine.getSupportedProtocols();
+        SUPPORTED_PROTOCOLS = new HashSet<>(supportedProtocols.length);
+        Collections.addAll(SUPPORTED_PROTOCOLS, supportedProtocols);
+
         // Choose the sensible default list of cipher suites.
         final String[] supportedCiphers = engine.getSupportedCipherSuites();
         SUPPORTED_CIPHERS = new HashSet<>(supportedCiphers.length);
         Collections.addAll(SUPPORTED_CIPHERS, supportedCiphers);
-        List enabledCiphers = new ArrayList<>();
-        addIfSupported(SUPPORTED_CIPHERS, enabledCiphers,
-                // GCM (Galois/Counter Mode) requires JDK 8.
-                "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
-                // AES256 requires JCE unlimited strength jurisdiction
-                // policy files.
-                "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
-                // GCM (Galois/Counter Mode) requires JDK 8.
-                "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA",
-                // AES256 requires JCE unlimited strength jurisdiction
-                // policy files.
-                "TLS_RSA_WITH_AES_256_CBC_SHA");
-
-        if (enabledCiphers.isEmpty()) {
-            // Use the default from JDK as fallback.
-            for (String cipher : engine.getEnabledCipherSuites()) {
-                if (cipher.contains("_RC4_")) {
-                    continue;
-                }
-                enabledCiphers.add(cipher);
-            }
-        }
-        ENABLED_CIPHERS = Collections.unmodifiableList(enabledCiphers);
-    }
-
-    private final String[] applicationProtocols;
-
-    private final String[] cipherSuites;
-
-    private final ClientAuth clientAuth;
 
+        // default protocols
+        List defaultProtocols = new ArrayList<>();
+        defaultProtocols.add("TLSv1.3");
+        defaultProtocols.add("TLSv1.2");
+        defaultProtocols.add("TLSv1.1");
+
+        // ECDHE == PFS
+        List defaultCiphers = new ArrayList<>();
+        // GCM (Galois/Counter Mode) requires JDK 8.
+        defaultCiphers.add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
+        defaultCiphers.add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256");
+        defaultCiphers.add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
+        defaultCiphers.add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
+        // AES256 requires JCE unlimited strength jurisdiction policy files.
+        defaultCiphers.add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA");
+        // GCM (Galois/Counter Mode) requires JDK 8.
+        defaultCiphers.add("TLS_RSA_WITH_AES_128_GCM_SHA256");
+        defaultCiphers.add("TLS_RSA_WITH_AES_128_CBC_SHA");
+        // AES256 requires JCE unlimited strength jurisdiction policy files.
+        defaultCiphers.add("TLS_RSA_WITH_AES_256_CBC_SHA");
+
+        DEFAULT_PROTOCOLS = Collections.unmodifiableList(defaultProtocols);
+        DEFAULT_CIPHERS = Collections.unmodifiableList(defaultCiphers);
+    }
+
+    private final String[]     applicationProtocols;
+    private final String[]     cipherSuites;
+    private final String[]     protocols;
+    private final ClientAuth   clientAuth;
     private final boolean      isServer;
     private final SSLContext   sslContext;
     private final List unmodifiableCipherSuites;
+    private final List unmodifiableProtocols;
 
-    SslContext(SSLContext sslContext, boolean isServer, List ciphers, ClientAuth clientAuth, String[] applicationProtocols) throws SSLException {
+    SslContext(SSLContext sslContext, boolean isServer, List protocols, List ciphers, ClientAuth clientAuth, String[] applicationProtocols) throws SSLException {
         this.applicationProtocols = applicationProtocols;
         this.clientAuth = clientAuth;
-        this.cipherSuites = filterCipherSuites(ciphers, ENABLED_CIPHERS, SUPPORTED_CIPHERS);
+        this.cipherSuites = filterCipherSuites(ciphers, DEFAULT_CIPHERS, SUPPORTED_CIPHERS);
+        this.protocols = filterCipherSuites(protocols, DEFAULT_PROTOCOLS, SUPPORTED_PROTOCOLS);
         this.unmodifiableCipherSuites = Collections.unmodifiableList(Arrays.asList(cipherSuites));
+        this.unmodifiableProtocols = Collections.unmodifiableList(Arrays.asList(this.protocols));
         this.sslContext = sslContext;
         this.isServer = isServer;
         if (applicationProtocols != null && !OPENSSL_AVAILABLE) {
@@ -153,14 +152,19 @@ static SSLContext newSSLContext() throws NoSuchAlgorithmException {
         }
     }
 
-    public final List cipherSuites() {
+    public final List getCipherSuites() {
         return unmodifiableCipherSuites;
     }
 
+    public final List getProtocols() {
+        return unmodifiableProtocols;
+    }
+
     private SSLEngine configureEngine(SSLEngine engine) {
         engine.setEnabledCipherSuites(cipherSuites);
-        engine.setEnabledProtocols(ENABLED_PROTOCOLS);
+        engine.setEnabledProtocols(protocols);
         engine.setUseClientMode(isClient());
+
         if (isServer()) {
             if (clientAuth == ClientAuth.OPTIONAL) {
                 engine.setWantClientAuth(true);
@@ -176,20 +180,17 @@ private SSLEngine configureEngine(SSLEngine engine) {
     }
 
     private String[] filterCipherSuites(List ciphers, List defaultCiphers, Set supportedCiphers) {
-        if (ciphers == null) {
-            return defaultCiphers.toArray(new String[0]);
-        } else {
-            List newCiphers = new ArrayList<>();
-            for (String c : ciphers) {
-                if (c == null) {
-                    break;
-                }
-                if (supportedCiphers.contains(c)) {
-                    newCiphers.add(c);
-                }
+        List filter_ciphers = ciphers;
+        if (filter_ciphers == null) {
+            filter_ciphers = defaultCiphers;
+        }
+        List newCiphers = new ArrayList<>();
+        for (String c : filter_ciphers) {
+            if (supportedCiphers.contains(c)) {
+                newCiphers.add(c);
             }
-            return newCiphers.toArray(new String[0]);
         }
+        return newCiphers.toArray(new String[0]);
     }
 
     public SSLContext getSSLContext() {
diff --git a/firenio-core/src/main/java/com/firenio/component/SslContextBuilder.java b/firenio-core/src/main/java/com/firenio/component/SslContextBuilder.java
index 82c2014b2..209fdc1bd 100644
--- a/firenio-core/src/main/java/com/firenio/component/SslContextBuilder.java
+++ b/firenio-core/src/main/java/com/firenio/component/SslContextBuilder.java
@@ -16,9 +16,6 @@
 package com.firenio.component;
 
 import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.security.InvalidAlgorithmParameterException;
@@ -57,6 +54,7 @@
 import com.firenio.common.Cryptos;
 import com.firenio.common.FileUtil;
 import com.firenio.common.Util;
+import com.firenio.component.SslContext.ClientAuth;
 
 /**
  * Builder for configuring a new SslContext for creation.
@@ -66,13 +64,15 @@ public final class SslContextBuilder {
 
     private String[]              applicationProtocols;
     private List          ciphers;
-    private SslContext.ClientAuth clientAuth = SslContext.ClientAuth.NONE;
+    private List          protocols;
+    private ClientAuth            clientAuth = ClientAuth.NONE;
+    private TrustType             trustType;
     private boolean               isServer;
     private KeyManagerFactory     keyManagerFactory;
     private long                  sessionCacheSize;
     private long                  sessionTimeout;
     private TrustManagerFactory   trustManagerFactory;
-    private TrustType             trustType  = TrustType.NONE;
+    private List rawX509Certificates;
     private X509TrustManager      x509TrustManager;
 
     private SslContextBuilder(boolean isServer) {
@@ -80,25 +80,13 @@ private SslContextBuilder(boolean isServer) {
     }
 
     public static SslContextBuilder forClient(boolean trustAll) {
-        return new SslContextBuilder(false).trustManager(trustAll);
+        return new SslContextBuilder(false).trust(trustAll);
     }
 
     public static SslContextBuilder forServer() {
         return new SslContextBuilder(true);
     }
 
-    static List readCertificates(File file) throws CertificateException {
-        InputStream in = null;
-        try {
-            in = new FileInputStream(file);
-            return readCertificates(in);
-        } catch (FileNotFoundException e) {
-            throw new CertificateException("could not find certificate file: " + file);
-        } finally {
-            Util.close(in);
-        }
-    }
-
     static List readCertificates(InputStream in) throws CertificateException {
         List ls;
         try {
@@ -106,10 +94,13 @@ static List readCertificates(InputStream in) throws CertificateException
         } catch (IOException e) {
             throw new CertificateException("failed to native_read certificate input stream", e);
         }
+        return readCertificates(ls);
+    }
+
+    static List readCertificates(List ls) throws CertificateException {
         List  certs   = new ArrayList<>();
         StringBuilder b       = new StringBuilder();
         int           readEnd = 0;
-
         for (String s : ls) {
             if (s.startsWith("----")) {
                 readEnd++;
@@ -124,7 +115,7 @@ static List readCertificates(InputStream in) throws CertificateException
             b.append(s.trim().replace("\r", ""));
         }
         if (certs.isEmpty()) {
-            throw new CertificateException("found no certificates in input stream");
+            throw new CertificateException("found no certificate in input stream");
         }
         return certs;
     }
@@ -136,7 +127,7 @@ public SslContextBuilder applicationProtocols(String[] applicationProtocols) {
 
     public SslContext build() throws SSLException {
         SSLContext context = newSSLContext();
-        return new SslContext(context, isServer, ciphers, clientAuth, applicationProtocols);
+        return new SslContext(context, isServer, protocols, ciphers, clientAuth, applicationProtocols);
     }
 
     private KeyManagerFactory buildKeyManagerFactory(KeyStore ks, char[] keyPasswordChars) throws SSLException {
@@ -199,6 +190,12 @@ public SslContextBuilder ciphers(List ciphers) {
         return this;
     }
 
+    public SslContextBuilder protocols(List protocols) {
+        needServer();
+        this.protocols = protocols;
+        return this;
+    }
+
     public SslContextBuilder clientAuth(SslContext.ClientAuth clientAuth) {
         needServer();
         this.clientAuth = clientAuth;
@@ -260,7 +257,7 @@ public SslContextBuilder keyManager(InputStream keyInput, InputStream certChainI
         try {
             keyCertChain = toX509Certificates(certChainInput);
         } catch (Exception e) {
-            throw new IllegalArgumentException("Input stream not contain valid certificates.", e);
+            throw new IllegalArgumentException("Input stream not contain valid certificate.", e);
         } finally {
             Util.close(certChainInput);
         }
@@ -321,20 +318,31 @@ private SSLContext newSSLContext() throws SSLException {
             KeyManager[]   kms = null;
             if (isServer) {
                 kms = keyManagerFactory.getKeyManagers();
-            }
-            switch (trustType) {
-                case ALL:
-                    tms = new X509TrustManager[]{new TrustAllX509TrustManager()};
-                    break;
-                case TrustManagerFactory:
-                    tms = trustManagerFactory.getTrustManagers();
-                    break;
-                case X509TrustManager:
-                    tms = new X509TrustManager[]{x509TrustManager};
-                    break;
-                case NONE:
-                default:
-                    break;
+            } else {
+                switch (trustType) {
+                    case ALL:
+                        tms = new X509TrustManager[]{new TrustAllX509TrustManager()};
+                        break;
+                    case TrustManagerFactory:
+                        tms = trustManagerFactory.getTrustManagers();
+                        break;
+                    case X509TrustManager:
+                        tms = new X509TrustManager[]{x509TrustManager};
+                        break;
+                    case RawX509Certificate:
+                        if (rawX509Certificates.size() == 1) {
+                            tms = new X509TrustManager[]{new TrustOneX509TrustManager(rawX509Certificates.get(0))};
+                        } else {
+                            X509Certificate[] cs = rawX509Certificates.toArray(new X509Certificate[0]);
+                            tms = new X509TrustManager[]{new TrustX509TrustManager(cs)};
+                        }
+                        break;
+                    default:
+                        if (!isServer) {
+                            throw new SSLException("did not trust anything");
+                        }
+                        break;
+                }
             }
             ctx.init(kms, tms, new SecureRandom());
             SSLSessionContext sessCtx;
@@ -375,27 +383,41 @@ private PrivateKey toPrivateKey(InputStream keyInputStream, String keyPassword)
         return getPrivateKeyFromByteBuffer(readCertificates(keyInputStream).get(0), keyPassword);
     }
 
-    private X509Certificate[] toX509Certificates(InputStream in) throws CertificateException {
+    public X509Certificate[] toX509Certificates(InputStream in) throws CertificateException {
         Assert.notNull(in, "null inputstream");
         return getCertificatesFromBuffers(readCertificates(in));
     }
 
-    public SslContextBuilder trustManager(boolean trustAll) {
+    public X509Certificate[] toX509Certificates(List ls) throws CertificateException {
+        Assert.notNull(ls, "null ls");
+        return getCertificatesFromBuffers(readCertificates(ls));
+    }
+
+    public SslContextBuilder trust(boolean trustAll) {
         needClient();
         trustType = trustAll ? TrustType.ALL : trustType;
         return this;
     }
 
-    public SslContextBuilder trustManager(InputStream trustCertCollectionInputStream) {
+    public SslContextBuilder trust(InputStream trustCertCollectionInputStream) {
         needClient();
         try {
-            return trustManager(toX509Certificates(trustCertCollectionInputStream));
+            return trust(toX509Certificates(trustCertCollectionInputStream));
         } catch (Exception e) {
-            throw new IllegalArgumentException("Input stream does not contain valid certificates.", e);
+            throw new IllegalArgumentException("Input stream does not contain valid certificate.", e);
         }
     }
 
-    public SslContextBuilder trustManager(TrustManagerFactory trustManagerFactory) {
+    public SslContextBuilder trust(List trustCertCollectionLines) {
+        needClient();
+        try {
+            return trust(toX509Certificates(trustCertCollectionLines));
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Input stream does not contain valid certificate.", e);
+        }
+    }
+
+    public SslContextBuilder trust(TrustManagerFactory trustManagerFactory) {
         needClient();
         Assert.notNull(trustManagerFactory, "null trustManagerFactory");
         this.trustManagerFactory = trustManagerFactory;
@@ -403,14 +425,37 @@ public SslContextBuilder trustManager(TrustManagerFactory trustManagerFactory) {
         return this;
     }
 
-    public SslContextBuilder trustManager(X509Certificate... trustCertCollection) throws SSLException {
+    public SslContextBuilder trustRaw(InputStream trustCertCollection) throws CertificateException {
+        return trustRaw(toX509Certificates(trustCertCollection));
+    }
+
+    public SslContextBuilder trustRaw(List trustCertCollection) throws CertificateException {
+        return trustRaw(toX509Certificates(trustCertCollection));
+    }
+
+    public SslContextBuilder trustRaw(X509Certificate... trustCertCollection) {
+        needClient();
+        Assert.notEmpty(trustCertCollection, "empty trustCertCollection");
+        if (rawX509Certificates == null) {
+            rawX509Certificates = new ArrayList<>(trustCertCollection.length);
+        }
+        for (X509Certificate certificate : trustCertCollection) {
+            if (certificate != null) {
+                rawX509Certificates.add(certificate);
+            }
+        }
+        trustType = TrustType.RawX509Certificate;
+        return this;
+    }
+
+    public SslContextBuilder trust(X509Certificate... trustCertCollection) throws SSLException {
         needClient();
         Assert.notEmpty(trustCertCollection, "empty trustCertCollection");
-        trustManager(buildTrustManagerFactory(trustCertCollection));
+        trust(buildTrustManagerFactory(trustCertCollection));
         return this;
     }
 
-    public SslContextBuilder trustManager(X509TrustManager x509TrustManager) {
+    public SslContextBuilder trust(X509TrustManager x509TrustManager) {
         needClient();
         Assert.notNull(x509TrustManager, "null x509TrustManager");
         this.x509TrustManager = x509TrustManager;
@@ -420,17 +465,78 @@ public SslContextBuilder trustManager(X509TrustManager x509TrustManager) {
 
     enum TrustType {
 
-        ALL, NONE, TrustManagerFactory, X509TrustManager
+        ALL, TrustManagerFactory, X509TrustManager, RawX509Certificate
+
+    }
+
+    static class TrustAllX509TrustManager implements X509TrustManager {
+
+        @Override
+        public void checkClientTrusted(X509Certificate[] arg0, String arg1) {}
+
+        @Override
+        public void checkServerTrusted(X509Certificate[] arg0, String arg1) { }
+
+        @Override
+        public X509Certificate[] getAcceptedIssuers() {
+            return null;
+        }
 
     }
 
-    class TrustAllX509TrustManager implements X509TrustManager {
+
+    static class TrustX509TrustManager implements X509TrustManager {
+
+        final X509Certificate[] certificates;
+
+        TrustX509TrustManager(X509Certificate[] certificates) {
+            this.certificates = certificates;
+        }
 
         @Override
         public void checkClientTrusted(X509Certificate[] arg0, String arg1) {}
 
         @Override
-        public void checkServerTrusted(X509Certificate[] arg0, String arg1) {}
+        public void checkServerTrusted(X509Certificate[] server_certs, String arg1) throws CertificateException {
+            for (int i = 0; i < certificates.length; i++) {
+                X509Certificate client_cert = certificates[i];
+                for (int j = 0; j < server_certs.length; j++) {
+                    if (client_cert.equals(server_certs[j])) {
+                        return;
+                    }
+                }
+            }
+            throw new CertificateException();
+        }
+
+        @Override
+        public X509Certificate[] getAcceptedIssuers() {
+            return null;
+        }
+
+    }
+
+    static class TrustOneX509TrustManager implements X509TrustManager {
+
+        X509Certificate certificate;
+
+        TrustOneX509TrustManager(X509Certificate certificate) {
+            this.certificate = certificate;
+        }
+
+        @Override
+        public void checkClientTrusted(X509Certificate[] arg0, String arg1) {}
+
+        @Override
+        public void checkServerTrusted(X509Certificate[] server_certs, String arg1) throws CertificateException {
+            X509Certificate client_cert = certificate;
+            for (int i = 0; i < server_certs.length; i++) {
+                if (client_cert.equals(server_certs[i])) {
+                    return;
+                }
+            }
+            throw new CertificateException();
+        }
 
         @Override
         public X509Certificate[] getAcceptedIssuers() {
diff --git a/firenio-core/src/main/java/com/firenio/concurrent/ExecutorEventLoop.java b/firenio-core/src/main/java/com/firenio/concurrent/ExecutorEventLoop.java
index 172d6a6b4..138cc7b85 100644
--- a/firenio-core/src/main/java/com/firenio/concurrent/ExecutorEventLoop.java
+++ b/firenio-core/src/main/java/com/firenio/concurrent/ExecutorEventLoop.java
@@ -39,7 +39,7 @@ private static void runJob(Runnable job) {
         if (job != null) {
             try {
                 job.run();
-            } catch (Exception e) {
+            } catch (Throwable e) {
                 logger.error(e.getMessage(), e);
             }
         }
diff --git a/firenio-core/src/main/java/com/firenio/concurrent/ScmpLinkedQueue.java b/firenio-core/src/main/java/com/firenio/concurrent/ScmpLinkedQueue.java
deleted file mode 100644
index 26c72cc32..000000000
--- a/firenio-core/src/main/java/com/firenio/concurrent/ScmpLinkedQueue.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2015 The FireNio Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.firenio.concurrent;
-
-import com.firenio.common.Unsafe;
-
-public class ScmpLinkedQueue extends ScspLinkedQueue {
-
-    private static final long tailOffset;
-
-    static {
-        try {
-            tailOffset = Unsafe.objectFieldOffset(ScspLinkedQueue.class.getDeclaredField("tail"));
-        } catch (Exception e) {
-            throw new Error(e);
-        }
-    }
-
-    public void offer(V v) {
-        Node n    = new Node<>();
-        Node tail = getTail();
-        if (Unsafe.compareAndSwapObject(this, tailOffset, tail, n)) {
-            tail.v = v;
-            tail.next = n;
-            incrementAndGet();
-            return;
-        }
-        for (; ; ) {
-            tail = getTail();
-            if (Unsafe.compareAndSwapObject(this, tailOffset, tail, n)) {
-                tail.v = v;
-                tail.next = n;
-                incrementAndGet();
-                return;
-            }
-        }
-    }
-
-}
diff --git a/firenio-core/src/main/java/com/firenio/concurrent/ScspLinkedQueue.java b/firenio-core/src/main/java/com/firenio/concurrent/ScspLinkedQueue.java
deleted file mode 100644
index 36a573483..000000000
--- a/firenio-core/src/main/java/com/firenio/concurrent/ScspLinkedQueue.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2015 The FireNio Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.firenio.concurrent;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-public class ScspLinkedQueue {
-
-    //     not sure if this useful
-    long p00, p01, p02, p03, p04, p05, p06, p07;
-    long p10, p11, p12, p13, p14, p15, p16, p17;
-    private volatile Node head = null;                           // volatile ?
-    private AtomicInteger size = new AtomicInteger();
-
-    private volatile Node tail = null;
-
-    public ScspLinkedQueue() {
-        this.head = new Node<>();
-        this.tail = head;
-    }
-
-    Node getTail() {
-        return tail;
-    }
-
-    protected int incrementAndGet() {
-        return size.incrementAndGet();
-    }
-
-    public void offer(V v) {
-        Node node = new Node<>();
-        tail.v = v;
-        tail.next = node;
-        tail = node;
-        size.incrementAndGet();
-    }
-
-    public V poll() {
-        if (size.get() == 0) {
-            return null;
-        }
-        size.decrementAndGet();
-        Node h = head;
-        head = h.next;
-        return h.v;
-    }
-
-    public int size() {
-        return size.get();
-    }
-
-    static class Node {
-        Node next;
-        V       v;
-    }
-
-}
diff --git a/firenio-core/src/main/java/com/firenio/concurrent/ThreadEventLoop.java b/firenio-core/src/main/java/com/firenio/concurrent/ThreadEventLoop.java
index 3d962f9c8..f0272b903 100644
--- a/firenio-core/src/main/java/com/firenio/concurrent/ThreadEventLoop.java
+++ b/firenio-core/src/main/java/com/firenio/concurrent/ThreadEventLoop.java
@@ -37,7 +37,7 @@ private static void runJob(Runnable job) {
         if (job != null) {
             try {
                 job.run();
-            } catch (Exception e) {
+            } catch (Throwable e) {
                 logger.error(e.getMessage(), e);
             }
         }
@@ -49,7 +49,7 @@ protected void doLoop() throws InterruptedException {
     }
 
     @Override
-    protected void doStart() throws Exception {
+    protected void doStart() {
         int maxQueueSize = group.getMaxQueueSize();
         this.jobs = new ArrayBlockingQueue<>(maxQueueSize);
     }
diff --git a/firenio-core/src/main/java/com/firenio/concurrent/Waiter.java b/firenio-core/src/main/java/com/firenio/concurrent/Waiter.java
index d2f3fb806..a750397c1 100644
--- a/firenio-core/src/main/java/com/firenio/concurrent/Waiter.java
+++ b/firenio-core/src/main/java/com/firenio/concurrent/Waiter.java
@@ -42,12 +42,6 @@ public void await() {
         await(0);
     }
 
-    /**
-     * return true is timeout
-     *
-     * @param timeout
-     * @return timeouted
-     */
     public void await(long timeout) {
         synchronized (lock) {
             if (!isDone) {
diff --git a/firenio-core/src/main/resources/native.o b/firenio-core/src/main/resources/native.o
old mode 100644
new mode 100755
index 1e38cb1ec..c4269f0c8
Binary files a/firenio-core/src/main/resources/native.o and b/firenio-core/src/main/resources/native.o differ
diff --git a/firenio-epoll/src/Native.cpp b/firenio-epoll/src/Native.cpp
index 29a56e549..d65ab8474 100644
--- a/firenio-epoll/src/Native.cpp
+++ b/firenio-epoll/src/Native.cpp
@@ -3,6 +3,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -12,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 
@@ -294,6 +296,51 @@ static inline int make_socket_non_blocking(int fd){
     return 0;
 }
 
+JNIEXPORT jint JNICALL Java_com_firenio_component_Native_open0
+  (JNIEnv * e, jclass c,jstring path,jint op, jint pem){
+    const char *file_path = e->GetStringUTFChars(path, NULL);
+    return open(file_path, op, pem);
+  }
+
+JNIEXPORT jlong JNICALL Java_com_firenio_component_Native_posix_1memalign_1allocate0
+  (JNIEnv * e, jclass c, jint len, jint align){
+    unsigned char *buf;
+    int ret = posix_memalign((void **) &buf, align, len);
+    if (ret < 0) {
+        return ret;
+    }
+    return (jlong) buf;
+  }
+
+JNIEXPORT jlong JNICALL Java_com_firenio_component_Native_file_1length0
+  (JNIEnv * e, jclass c, jint fd){
+    struct stat stbuf;  
+    int ret = fstat(fd, &stbuf);
+    if (( ret < 0) ) {
+      return ret;
+    }
+    if((!S_ISREG(stbuf.st_mode))){
+      return 0;
+    }
+    return (jlong)(stbuf.st_size);
+  }
+
+JNIEXPORT jlong JNICALL Java_com_firenio_component_Native_lseek0
+  (JNIEnv * e, jclass c, jint fd, jlong off, jint seek_mode){
+    return (jlong)(lseek(fd, off, seek_mode));
+  }
+
+JNIEXPORT jint JNICALL Java_com_firenio_component_Native_pread0
+  (JNIEnv * e, jclass c, jint fd, jlong address, jint len, jlong off){
+    return pread(fd, (void *)address, len, off);
+  }
+
+JNIEXPORT jint JNICALL Java_com_firenio_component_Native_pwrite0
+  (JNIEnv * e, jclass c, jint fd, jlong address, jint len, jlong off){
+    return pwrite(fd, (void *)address, len, off);
+  }
+
+
 int main(){ return 0;}
 
 #ifdef __cplusplus
diff --git a/firenio-homepage/conf/server.properties b/firenio-homepage/conf/server.properties
index 06666b09e..8cf12842e 100644
--- a/firenio-homepage/conf/server.properties
+++ b/firenio-homepage/conf/server.properties
@@ -25,3 +25,4 @@ server.writeBuffers=8
 app.enableHttp2=false
 #app.webRoot=C:/GIT/weixin-h5
 app.welcome=/index.html
+app.proxy=false
diff --git a/firenio-homepage/http-startup.sh b/firenio-homepage/http-startup.sh
index 1e585f0e3..17dc9494e 100644
--- a/firenio-homepage/http-startup.sh
+++ b/firenio-homepage/http-startup.sh
@@ -1,3 +1,5 @@
+#!/bin/bash
+
 cd ../firenio
 mvn clean install -DskipTests
 
@@ -23,9 +25,13 @@ done
 PRG="$0"
 PRGDIR=`dirname "$PRG"`
 
-java -XX:+PrintGCDetails -Xloggc:gc.log -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=6666,suspend=n \
+(java -XX:+PrintGCDetails -Xloggc:gc.log -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=6666,suspend=n \
      -cp $CLASSPATH \
      -Dboot.mode=prod \
      -Dboot.libPath=/app/lib \
+     -Dorg.wildfly.openssl.path=$1 \
      -Dboot.class=sample.http11.startup.TestHttpBootstrapEngine \
-     com.firenio.container.Bootstrap
+     com.firenio.container.Bootstrap) &
+
+## echo -17 > /proc/$(ps -ef | grep java | grep -v grep | awk '{print $2}')/oom_adj && cat /proc/$(ps -ef | grep java | grep -v grep | awk '{print $2}')/oom_adj
+
diff --git a/firenio-sample/sample-http/pom.xml b/firenio-sample/sample-http/pom.xml
index 47ad79a11..c244e3941 100644
--- a/firenio-sample/sample-http/pom.xml
+++ b/firenio-sample/sample-http/pom.xml
@@ -105,7 +105,7 @@
 		
 			com.alibaba
 			fastjson
-			1.2.31
+			1.2.62
 		
 
 		
@@ -117,25 +117,25 @@
 		
 			com.firenio
 			firenio-codec
-			1.2.2-SNAPSHOT
+			1.3.2-SNAPSHOT
 		
 
 		
 			org.wildfly.openssl
 			wildfly-openssl-windows-x86_64
-			1.0.6.Final
+			1.0.8.Final
 		
 
 		
 			org.wildfly.openssl
 			wildfly-openssl-linux-x86_64
-			1.0.6.Final
+			1.0.8.Final
 		
 
 		
 			org.wildfly.openssl
 			wildfly-openssl-java
-			1.0.6.Final
+			1.0.8.Final
 		
 		
 			javax.annotation
diff --git a/firenio-sample/sample-http/src/main/java/sample/http11/HttpFrameHandle.java b/firenio-sample/sample-http/src/main/java/sample/http11/HttpFrameHandle.java
index 3a8cb7ca6..3ac8fe1ba 100644
--- a/firenio-sample/sample-http/src/main/java/sample/http11/HttpFrameHandle.java
+++ b/firenio-sample/sample-http/src/main/java/sample/http11/HttpFrameHandle.java
@@ -39,7 +39,7 @@
 import com.firenio.log.Logger;
 import com.firenio.log.LoggerFactory;
 
-//FIXME limit too large file
+//FIXME writeIndex too large file
 public class HttpFrameHandle extends IoEventHandle {
 
     private Charset                 charset        = Util.UTF8;
@@ -97,7 +97,7 @@ protected void acceptHtml(Channel ch, Frame frame) throws Exception {
     public void destroy(ChannelContext context) {}
 
     @Override
-    public void exceptionCaught(Channel ch, Frame frame, Exception ex) {
+    public void exceptionCaught(Channel ch, Frame frame, Throwable ex) {
         logger.error(ex.getMessage(), ex);
         frame.release();
         if (!ch.isOpen()) {
@@ -347,9 +347,7 @@ long getLastModifyGTMTime() {
         }
 
         void setBinary(byte[] readBytesByFile) {
-            ByteBuf content = ByteBuf.wrap(readBytesByFile);
-            content.position(content.limit());
-            this.content = content;
+            this.content = ByteBuf.wrapAuto(readBytesByFile);
         }
 
         void setContentType(HttpContentType contentType) {
diff --git a/firenio-sample/sample-http/src/main/java/sample/http11/proxy/HttpProxyServer.java b/firenio-sample/sample-http/src/main/java/sample/http11/proxy/HttpProxyServer.java
index b2168e31a..7d703c0cd 100644
--- a/firenio-sample/sample-http/src/main/java/sample/http11/proxy/HttpProxyServer.java
+++ b/firenio-sample/sample-http/src/main/java/sample/http11/proxy/HttpProxyServer.java
@@ -30,7 +30,6 @@
 import com.firenio.component.Channel;
 import com.firenio.component.ChannelAcceptor;
 import com.firenio.component.ChannelConnector;
-import com.firenio.component.ChannelEventListenerAdapter;
 import com.firenio.component.Frame;
 import com.firenio.component.IoEventHandle;
 import com.firenio.component.LoggerChannelOpenListener;
@@ -41,7 +40,7 @@
 public class HttpProxyServer {
 
     static final String          CONNECT_RES     = "HTTP/1.1 200 Connection Established\r\n\r\n";
-    static final ByteBuf         CONNECT_RES_BUF = ByteBuf.wrap(CONNECT_RES.getBytes());
+    static final ByteBuf         CONNECT_RES_BUF = ByteBuf.wrapAuto(CONNECT_RES.getBytes());
     static final HttpProxyServer server          = new HttpProxyServer();
     private      ChannelAcceptor context;
 
@@ -106,7 +105,7 @@ public void accept(Channel ch, Frame frame) throws Exception {
                             ClientHttpFrame res = (ClientHttpFrame) frame;
                             IntMap  hs  = res.getResponse_headers();
                             for (hs.scan(); hs.hasNext(); ) {
-                                String v = hs.nextValue();
+                                String v = hs.value();
                                 if (v == null) {
                                     continue;
                                 }
@@ -126,7 +125,6 @@ public void accept(Channel ch, Frame frame) throws Exception {
                     });
                     String url = parseRequestURL(f.getRequestURL());
                     context.setPrintConfig(false);
-                    context.addChannelEventListener(new HttpProxyAttrListener());
                     context.addChannelEventListener(new LoggerChannelOpenListener());
                     context.connect((ch, ex) -> {
                         if (ex == null) {
@@ -150,20 +148,16 @@ public void accept(Channel ch, Frame frame) throws Exception {
         context = new ChannelAcceptor(group, 8088);
         context.addProtocolCodec(new HttpProxyCodec());
         context.setIoEventHandle(eventHandle);
-        context.addChannelEventListener(new HttpProxyAttrListener());
         context.addChannelEventListener(new LoggerChannelOpenListener());
         context.bind();
     }
 
-    static class HttpProxyAttrListener extends ChannelEventListenerAdapter {
+    static class HttpProxyCodec extends HttpCodec {
 
         @Override
-        public void channelOpened(Channel ch) {
-            ch.setAttachment(new HttpProxyAttr());
+        protected Object newAttachment() {
+            return new HttpProxyAttr();
         }
-    }
-
-    static class HttpProxyCodec extends HttpCodec {
 
         @Override
         public Frame decode(final Channel ch_src, ByteBuf src) throws Exception {
@@ -176,14 +170,9 @@ public Frame decode(final Channel ch_src, ByteBuf src) throws Exception {
 
                         @Override
                         public Frame decode(Channel ch, ByteBuf src) {
-                            ByteBuf buf = ch_src.alloc().allocate(src.remaining());
-                            buf.putBytes(src);
-                            ch_src.writeAndFlush(buf.flip());
-                            return null;
-                        }
-
-                        @Override
-                        public ByteBuf encode(Channel ch, Frame frame) {
+                            ByteBuf buf = ch_src.alloc().allocate(src.readableBytes());
+                            buf.writeBytes(src);
+                            ch_src.writeAndFlush(buf);
                             return null;
                         }
 
@@ -199,12 +188,12 @@ public int getHeaderLength() {
                     });
                     context.setPrintConfig(false);
                     context.addChannelEventListener(new LoggerChannelOpenListener());
-                    ByteBuf buf = ch_src.alloc().allocate(src.remaining());
-                    buf.putBytes(src);
+                    ByteBuf buf = ch_src.alloc().allocate(src.readableBytes());
+                    buf.writeBytes(src);
                     s.connector = context;
                     s.connector.connect((ch_target, ex) -> {
                         if (ex == null) {
-                            ch_target.writeAndFlush(buf.flip());
+                            ch_target.writeAndFlush(buf);
                         } else {
                             buf.release();
                             HttpProxyAttr.remove(ch_src);
@@ -212,9 +201,9 @@ public int getHeaderLength() {
                         }
                     });
                 } else {
-                    ByteBuf buf = ch_src.alloc().allocate(src.remaining());
-                    buf.putBytes(src);
-                    s.connector.getChannel().writeAndFlush(buf.flip());
+                    ByteBuf buf = ch_src.alloc().allocate(src.readableBytes());
+                    buf.writeBytes(src);
+                    s.connector.getChannel().writeAndFlush(buf);
                 }
                 return null;
             }
diff --git a/firenio-sample/sample-http/src/main/java/sample/http11/proxy4cloud/HttpProxy4CloudServer.java b/firenio-sample/sample-http/src/main/java/sample/http11/proxy4cloud/HttpProxy4CloudServer.java
index ae9503ad3..51d447ce1 100644
--- a/firenio-sample/sample-http/src/main/java/sample/http11/proxy4cloud/HttpProxy4CloudServer.java
+++ b/firenio-sample/sample-http/src/main/java/sample/http11/proxy4cloud/HttpProxy4CloudServer.java
@@ -19,6 +19,8 @@
 import java.net.InetSocketAddress;
 import java.net.Socket;
 
+import sample.http11.proxy.HttpProxyServer.HttpProxyAttr;
+
 import com.firenio.buffer.ByteBuf;
 import com.firenio.codec.http11.HttpAttachment;
 import com.firenio.codec.http11.HttpCodec;
@@ -41,7 +43,7 @@
 public class HttpProxy4CloudServer {
 
     static final String                CONNECT_RES     = "HTTP/1.1 200 Connection Established\r\n\r\n";
-    static final ByteBuf               CONNECT_RES_BUF = ByteBuf.wrap(CONNECT_RES.getBytes());
+    static final ByteBuf               CONNECT_RES_BUF = ByteBuf.wrapAuto(CONNECT_RES.getBytes());
     static final String                netHost;
     static final int                   netPort         = 18088;
     static final HttpProxy4CloudServer server          = new HttpProxy4CloudServer();
@@ -131,18 +133,12 @@ public Frame decode(final Channel ch_src, ByteBuf src) throws Exception {
                             @Override
                             public Frame decode(Channel ch, ByteBuf src) {
                                 Channel t   = (Channel) ch.getAttachment();
-                                ByteBuf buf = t.alloc().allocate(src.remaining());
-                                buf.putBytes(src);
-                                buf.flip();
+                                ByteBuf buf = t.alloc().allocate(src.readableBytes());
+                                buf.writeBytes(src);
                                 t.writeAndFlush(buf);
                                 return null;
                             }
 
-                            @Override
-                            public ByteBuf encode(Channel ch, Frame frame) {
-                                return null;
-                            }
-
                             @Override
                             public String getProtocolId() {
                                 return "http-proxy-connect";
@@ -163,12 +159,12 @@ public int getHeaderLength() {
                                 byte[]  host_bytes = host.getBytes();
                                 int     len        = 5 + host_bytes.length;
                                 ByteBuf head       = ch_target.alloc().allocate(len);
-                                head.putByte((byte) host_bytes.length);
-                                head.putByte((byte) 83);
-                                head.putByte((byte) 38);
-                                head.putShort(port);
-                                head.putBytes(host_bytes);
-                                ch_target.writeAndFlush(head.flip());
+                                head.writeByte((byte) host_bytes.length);
+                                head.writeByte((byte) 83);
+                                head.writeByte((byte) 38);
+                                head.writeShort(port);
+                                head.writeBytes(host_bytes);
+                                ch_target.writeAndFlush(head);
                                 el.schedule(new DelayTask(10) {
                                     @Override
                                     public void run() {
@@ -183,9 +179,8 @@ public void run() {
                 }
                 return null;
             } else {
-                ByteBuf buf = t.alloc().allocate(src.remaining());
-                buf.putBytes(src);
-                buf.flip();
+                ByteBuf buf = t.alloc().allocate(src.readableBytes());
+                buf.writeBytes(src);
                 t.writeAndFlush(buf);
             }
             return null;
diff --git a/firenio-sample/sample-http/src/main/java/sample/http11/proxy4cloud/NetDataTransferServer.java b/firenio-sample/sample-http/src/main/java/sample/http11/proxy4cloud/NetDataTransferServer.java
index 2e9bbf36a..b389209c9 100644
--- a/firenio-sample/sample-http/src/main/java/sample/http11/proxy4cloud/NetDataTransferServer.java
+++ b/firenio-sample/sample-http/src/main/java/sample/http11/proxy4cloud/NetDataTransferServer.java
@@ -68,7 +68,7 @@ public Frame decode(Channel ch, ByteBuf src) throws Exception {
             Channel t = (Channel) ch.getAttachment();
             if (t == null) {
                 short hostLen = src.getUnsignedByte(0);
-                if (src.remaining() < hostLen + 5) {
+                if (src.readableBytes() < hostLen + 5) {
                     ch.close();
                     return null;
                 }
@@ -80,8 +80,8 @@ public Frame decode(Channel ch, ByteBuf src) throws Exception {
                 }
                 byte[] hostBytes = new byte[hostLen];
                 int    port      = src.getUnsignedShort(3);
-                src.skip(5);
-                src.getBytes(hostBytes);
+                src.skipRead(5);
+                src.readBytes(hostBytes);
                 String           host    = new String(hostBytes);
                 NioEventLoop     el      = ch.getEventLoop();
                 ChannelConnector context = new ChannelConnector(el, host, port);
@@ -101,18 +101,12 @@ public Frame decode(Channel ch, ByteBuf src) throws Exception {
                 }, 10000);
                 return null;
             }
-            ByteBuf buf = t.alloc().allocate(src.remaining());
-            buf.putBytes(src);
-            buf.flip();
+            ByteBuf buf = t.alloc().allocate(src.readableBytes());
+            buf.writeBytes(src);
             t.writeAndFlush(buf);
             return null;
         }
 
-        @Override
-        public ByteBuf encode(Channel ch, Frame frame) {
-            return null;
-        }
-
         @Override
         public String getProtocolId() {
             return "NetDataTransfer";
diff --git a/firenio-sample/sample-http/src/main/java/sample/http11/service/TestEmojiServlet.java b/firenio-sample/sample-http/src/main/java/sample/http11/service/TestEmojiServlet.java
index 62a77c34c..759821bfd 100644
--- a/firenio-sample/sample-http/src/main/java/sample/http11/service/TestEmojiServlet.java
+++ b/firenio-sample/sample-http/src/main/java/sample/http11/service/TestEmojiServlet.java
@@ -45,7 +45,7 @@ protected void doAccept(Channel ch, HttpFrame frame) throws Exception {
 
         List emojiList = EmojiUtil.bytes2Emojis(emoji.getBytes(Util.UTF8));
 
-        String limitStr = frame.getRequestParam("limit");
+        String limitStr = frame.getRequestParam("writeIndex");
         int    limit;
         if (Util.isNullOrBlank(limitStr)) {
             limit = emojiList.size();
@@ -68,9 +68,7 @@ protected void doAccept(Channel ch, HttpFrame frame) throws Exception {
         builder.append(HttpUtil.HTML_POWER_BY);
         //        builder.append(getScript());
         builder.append(HttpUtil.HTML_BOTTOM);
-        ByteBuf buf = ByteBuf.wrap(builder.toString().getBytes(ch.getCharset()));
-        buf.position(buf.limit());
-        frame.setContent(buf);
+        frame.setContent(ByteBuf.wrapAuto(builder.toString().getBytes(ch.getCharset())));
         frame.setContentType(HttpContentType.text_html_utf8);
         ch.writeAndFlush(frame);
     }
diff --git a/firenio-sample/sample-http/src/main/java/sample/http11/service/TestShowMemoryServlet.java b/firenio-sample/sample-http/src/main/java/sample/http11/service/TestShowMemoryServlet.java
index 9bf73b726..b8664aaef 100644
--- a/firenio-sample/sample-http/src/main/java/sample/http11/service/TestShowMemoryServlet.java
+++ b/firenio-sample/sample-http/src/main/java/sample/http11/service/TestShowMemoryServlet.java
@@ -24,6 +24,7 @@
 import com.firenio.buffer.ByteBufAllocatorGroup;
 import com.firenio.codec.http11.HttpContentType;
 import com.firenio.codec.http11.HttpFrame;
+import com.firenio.collection.DelayedQueue.DelayTask;
 import com.firenio.common.DateUtil;
 import com.firenio.common.Util;
 import com.firenio.component.Channel;
@@ -49,7 +50,15 @@ protected void doAccept(Channel ch, HttpFrame f) throws Exception {
         String kill = f.getRequestParam("kill");
         if (!Util.isNullOrBlank(kill)) {
             Integer id = Integer.valueOf(kill, 16);
-            Util.close(CountChannelListener.chs.get(id));
+            Channel close_ch = CountChannelListener.chs.get(id);
+            if (close_ch != null){
+                close_ch.getEventLoop().schedule(new DelayTask(10) {
+                    @Override
+                    public void run() {
+                        Util.close(close_ch);
+                    }
+                });
+            }
         }
 
         BigDecimal time   = new BigDecimal(Util.now_f() - context.getStartupTime());
diff --git a/firenio-sample/sample-http/src/main/java/sample/http11/service/WebSocketMsgAdapter.java b/firenio-sample/sample-http/src/main/java/sample/http11/service/WebSocketMsgAdapter.java
index b97bfcbf9..3d1226002 100644
--- a/firenio-sample/sample-http/src/main/java/sample/http11/service/WebSocketMsgAdapter.java
+++ b/firenio-sample/sample-http/src/main/java/sample/http11/service/WebSocketMsgAdapter.java
@@ -21,7 +21,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 
-import com.firenio.codec.http11.WebSocketCodec;
+import com.firenio.buffer.ByteBuf;
 import com.firenio.codec.http11.WebSocketFrame;
 import com.firenio.component.Channel;
 import com.firenio.component.ChannelManager;
@@ -40,7 +40,7 @@ public WebSocketMsgAdapter(String threadName) {
         super(threadName);
     }
 
-    public void addClient(String username, Channel ch) {
+    public synchronized void addClient(String username, Channel ch) {
         clientMap.put(ch.getChannelId(), new Client(ch, username));
         channelMap.put(username, ch);
         logger.info("client joined {} ,clients size: {}", ch, clientMap.size());
@@ -52,23 +52,32 @@ protected void doLoop() throws InterruptedException {
         if (msg == null) {
             return;
         }
-        Channel ch = msg.ch;
-        if (ch != null) {
+        if (msg.ch != null) {
             WebSocketFrame f = new WebSocketFrame();
-            f.setString(msg.msg, ch);
+            f.setString(msg.msg, msg.ch);
             try {
-                ch.writeAndFlush(f);
+                msg.ch.writeAndFlush(f);
             } catch (Exception e) {
                 logger.error(e.getMessage(), e);
             }
         } else {
             if (!clientMap.isEmpty()) {
-                WebSocketFrame f = new WebSocketFrame();
-                f.setBytes(WebSocketCodec.MAX_HEADER_LENGTH, msg.msg.getBytes());
-                try {
-                    ChannelManager.broadcast(f, channelMap.values());
-                } catch (Exception e) {
-                    logger.error(e.getMessage(), e);
+                synchronized (this) {
+                    Client         client = clientMap.values().iterator().next();
+                    Channel        ch     = client.channel;
+                    WebSocketFrame f      = new WebSocketFrame();
+                    byte[]         data   = msg.msg.getBytes();
+                    ByteBuf        buf    = ch.allocate(data.length);
+                    buf.writeBytes(data);
+                    f.setContent(buf);
+                    ByteBuf buf2 = null;
+                    try {
+                        buf2 = ch.getCodec().encode(ch, f);
+                        ChannelManager.broadcast(buf2, channelMap.values());
+                    } catch (Exception e) {
+                        buf.release();
+                        logger.error(e.getMessage(), e);
+                    }
                 }
             }
         }
@@ -87,7 +96,7 @@ public BlockingQueue getJobs() {
         return msgs;
     }
 
-    public Client removeClient(Channel ch) {
+    public synchronized Client removeClient(Channel ch) {
         Client client = clientMap.remove(ch.getChannelId());
         if (client != null) {
             channelMap.remove(client.getUsername());
diff --git a/firenio-sample/sample-http/src/main/java/sample/http11/startup/TestHttpBootstrapEngine.java b/firenio-sample/sample-http/src/main/java/sample/http11/startup/TestHttpBootstrapEngine.java
index d91df29e1..4dc01fc1c 100644
--- a/firenio-sample/sample-http/src/main/java/sample/http11/startup/TestHttpBootstrapEngine.java
+++ b/firenio-sample/sample-http/src/main/java/sample/http11/startup/TestHttpBootstrapEngine.java
@@ -15,6 +15,10 @@
  */
 package sample.http11.startup;
 
+import sample.http11.SpringHttpFrameHandle;
+import sample.http11.proxy4cloud.NetDataTransferServer;
+import sample.http11.service.CountChannelListener;
+
 import com.firenio.DevelopConfig;
 import com.firenio.LifeCycle;
 import com.firenio.LifeCycleListener;
@@ -26,6 +30,7 @@
 import com.firenio.codec.http2.Http2Codec;
 import com.firenio.common.FileUtil;
 import com.firenio.common.Properties;
+import com.firenio.common.Util;
 import com.firenio.component.ChannelAcceptor;
 import com.firenio.component.ChannelAliveListener;
 import com.firenio.component.ConfigurationParser;
@@ -36,10 +41,6 @@
 import com.firenio.log.Logger;
 import com.firenio.log.LoggerFactory;
 
-import sample.http11.SpringHttpFrameHandle;
-import sample.http11.proxy4cloud.NetDataTransferServer;
-import sample.http11.service.CountChannelListener;
-
 /**
  * @author wangkai
  */
@@ -51,7 +52,11 @@ public class TestHttpBootstrapEngine implements BootstrapEngine {
     public void bootstrap(final String rootPath, final String mode) throws Exception {
         DevelopConfig.NATIVE_DEBUG = true;
         DevelopConfig.BUF_DEBUG = true;
+        DevelopConfig.SSL_DEBUG = true;
+        DevelopConfig.CHANNEL_DEBUG = true;
+        Options.setBufRecycle(false);
         Options.setEnableEpoll(true);
+        Options.setEnableUnsafe(true);
         Options.setEnableOpenssl(true);
         Options.setBufThreadYield(true);
         Options.setDebugError(true);
@@ -64,8 +69,8 @@ public void bootstrap(final String rootPath, final String mode) throws Exception
         ConfigurationParser.parseConfiguration("server.", context, properties);
         ConfigurationParser.parseConfiguration("server.", group, properties);
         context.setIoEventHandle(handle);
-        context.addChannelEventListener(new WebSocketChannelListener());
         context.addChannelIdleEventListener(new ChannelAliveListener());
+        context.addChannelEventListener(new WebSocketChannelListener());
         context.addChannelEventListener(new LoggerChannelOpenListener());
         context.addChannelEventListener(new CountChannelListener());
         context.setExecutorGroup(new ThreadEventLoopGroup());
@@ -92,7 +97,20 @@ public void lifeCycleStopped(LifeCycle lifeCycle) {
             context.addProtocolCodec(new WebSocketCodec());
         }
         context.bind();
-        NetDataTransferServer.get().startup(group, 18088);
+        if (properties.getBooleanProperty("app.proxy")) {
+            NetDataTransferServer.get().startup(group, 18088);
+        }
+        Util.exec(() -> {
+            Util.sleep(1000 * 60 * 30);
+            for (; ; ) {
+                Util.sleep(1000 * 60);
+                logger.info("server is running....:" + (Runtime.getRuntime().totalMemory() / 1024 / 1024));
+            }
+        });
+        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+            logger.info("server shutdown....");
+        }));
+
     }
 
 }
diff --git a/firenio-sample/sample-http/src/main/resources/app/html/favicon.ico b/firenio-sample/sample-http/src/main/resources/app/html/favicon.ico
index 57356136d..3dd6d4be8 100644
Binary files a/firenio-sample/sample-http/src/main/resources/app/html/favicon.ico and b/firenio-sample/sample-http/src/main/resources/app/html/favicon.ico differ
diff --git a/firenio-sample/sample-http/src/main/resources/server.properties b/firenio-sample/sample-http/src/main/resources/server.properties
index c8084b6af..8ba266850 100644
--- a/firenio-sample/sample-http/src/main/resources/server.properties
+++ b/firenio-sample/sample-http/src/main/resources/server.properties
@@ -1,16 +1,16 @@
 ###################################### server basic properties ######################################
 server.host=0.0.0.0
 server.port=
-server.bufRecycleSize
+server.bufRecycleSize=
 server.charset=utf-8
 server.channelReadBuffer=524288
 server.enableMemoryPool=true
-server.enableMemoryPoolDirect=true
+server.enableMemoryPoolDirect=
 server.enableHeartbeatLog=true
 server.enableWorkEventLoop=true
 server.eventLoopSize=2
 server.idleTime=300000
-server.memoryPoolRate
+server.memoryPoolRate=
 server.memoryPoolUnit=16
 server.memoryPoolCapacity=512000
 server.maxWriteBacklog=64
@@ -26,3 +26,4 @@ server.writeBuffers=8
 app.enableHttp2=false
 #app.webRoot=C:\\工作仓库\\yxaAdmin\\docs
 #app.welcome=/index.html
+app.proxy=false
diff --git a/firenio-test/pom.xml b/firenio-test/pom.xml
index 5da8b6cd8..e1de88335 100644
--- a/firenio-test/pom.xml
+++ b/firenio-test/pom.xml
@@ -93,13 +93,13 @@
         
             io.netty
             netty-all
-            4.1.36.Final
+            4.1.43.Final
         
 
         
             io.undertow
             undertow-core
-            2.0.16.Final
+            2.0.28.Final
         
 
         
@@ -117,13 +117,19 @@
         
             com.alibaba
             fastjson
-            1.2.49
+            1.2.62
         
 
         
             org.elasticsearch.client
             transport
             6.4.2
+            
+                
+                    io.netty
+                    *
+                
+            
         
 
         
diff --git a/firenio-test/src/main/java/test/io/Test1.java b/firenio-test/src/main/java/test/io/Test1.java
index 5d65e8944..f1963694e 100644
--- a/firenio-test/src/main/java/test/io/Test1.java
+++ b/firenio-test/src/main/java/test/io/Test1.java
@@ -11,61 +11,8 @@ public class Test1 {
 
     public static void main(String[] args) {
 
-        //        testMyMap();
-        //                testNettyMap();
-        Options.setSysClockStep(1);
-        System.out.println("t1:" + Util.now());
-        Util.sleep(100);
-        System.out.println("t2:" + Util.now());
-        long old   = Util.now_f();
-        long count = 1024 * 1024 * 512;
-        for (long i = 0; i < count; i++) {
-            Util.now();
-        }
-        long past = Util.past(old);
-        System.out.println("Time:" + past);
 
-    }
-
-    static void testNettyMap() {
-        Random         r   = new Random();
-        IntMap map = new IntMap<>(4, 0.75f);
-        for (int i = 0; i < 1000; i++) {
-            int    k = r.nextInt(Integer.MAX_VALUE);
-            String v = String.valueOf(k);
-            map.put(k, v);
-        }
-        DebugUtil.info("c:{}", map.conflict());
-    }
 
-    static void testMyMap() {
-        Random         r   = new Random();
-        IntMap map = new IntMap<>(4, 0.75f);
-        for (int i = 0; i < 20; i++) {
-            int    k = r.nextInt(Integer.MAX_VALUE);
-            String v = String.valueOf(k);
-            map.put(k, v);
-        }
-        DebugUtil.info("c:{}", map.conflict());
-        int s = 0;
-        for (map.scan(); map.hasNext(); ) {
-            s++;
-            int    i = map.next();
-            int    k = map.indexKey(i);
-            String v = map.indexValue(i);
-            if (i % 2 == 0) {
-                int idx = map.indexKey(i + 1);
-                if (idx != -1) {
-                    String res = map.remove(idx);
-                    if (res != null) {
-                        s++;
-                    }
-                }
-            } else {
-                map.remove(k);
-            }
-        }
-        DebugUtil.info("s:{}", s);
     }
 
 }
diff --git a/firenio-test/src/main/java/test/io/Test7.java b/firenio-test/src/main/java/test/io/Test7.java
new file mode 100644
index 000000000..3ad4a4d56
--- /dev/null
+++ b/firenio-test/src/main/java/test/io/Test7.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.io;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.Base64;
+
+import sun.reflect.misc.FieldUtil;
+
+import com.firenio.common.Cryptos;
+import com.firenio.common.FileUtil;
+import com.firenio.common.Unsafe;
+import com.firenio.common.Util;
+
+/**
+ * @author: wangkai
+ **/
+public class Test7 {
+
+    public static void main(String[] args) throws Exception {
+        String str   = "{\"X03\":\"G418Response\",\"X11\":false,\"X13\":true,\"X15\":4168,\"X17\":\"74137377\",\"X18\":\"zj003\",\"X19\":\"C\",\"X39\":\"00000000\",\"listData\":[{\"CUSTTRADEID\":\"0025110000000025\",\"INNERCLIENTID\":\"0000000001\",\"USERCODE\":\"_ST_0000000001\",\"CLIENTABBR\":\"自营紫金矿业\",\"SEATID\":\"002511\",\"CLIENTNAME\":\"紫金矿业\"},{\"CUSTTRADEID\":\"0025210100000900\",\"INNERCLIENTID\":\"0000000002\",\"USERCODE\":\"_ST_0000000002\",\"CLIENTABBR\":\"代理泉州宝辉\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"泉州宝辉\"},{\"CUSTTRADEID\":\"0025210100003161\",\"INNERCLIENTID\":\"0000000003\",\"USERCODE\":\"_ST_0000000003\",\"CLIENTABBR\":\"代理贵州紫金\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"贵州紫金\"},{\"CUSTTRADEID\":\"0025210100003251\",\"INNERCLIENTID\":\"0000000004\",\"USERCODE\":\"_ST_0000000004\",\"CLIENTABBR\":\"代理上杭金山\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"上杭金山\"},{\"CUSTTRADEID\":\"0025210100003374\",\"INNERCLIENTID\":\"0000000005\",\"USERCODE\":\"_ST_0000000005\",\"CLIENTABBR\":\"代理上杭华辉\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"上杭华辉\"},{\"CUSTTRADEID\":\"0025210100005310\",\"INNERCLIENTID\":\"0000000006\",\"USERCODE\":\"_ST_0000000006\",\"CLIENTABBR\":\"代理厦门紫金\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"厦门紫金\"},{\"CUSTTRADEID\":\"0025210100007075\",\"INNERCLIENTID\":\"0000000007\",\"USERCODE\":\"_ST_0000000007\",\"CLIENTABBR\":\"代理福建金怡\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"福建金怡\"},{\"CUSTTRADEID\":\"0025210100007693\",\"INNERCLIENTID\":\"0000000008\",\"USERCODE\":\"_ST_0000000008\",\"CLIENTABBR\":\"代理四川紫金\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"四川紫金\"},{\"CUSTTRADEID\":\"0025210100009459\",\"INNERCLIENTID\":\"0000000009\",\"USERCODE\":\"_ST_0000000009\",\"CLIENTABBR\":\"代理珲春紫金\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"珲春紫金\"},{\"CUSTTRADEID\":\"0025210100012093\",\"INNERCLIENTID\":\"0000000010\",\"USERCODE\":\"_ST_0000000010\",\"CLIENTABBR\":\"代理隆兴矿业\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"隆兴矿业\"},{\"CUSTTRADEID\":\"0025210100012543\",\"INNERCLIENTID\":\"0000000011\",\"USERCODE\":\"_ST_0000000011\",\"CLIENTABBR\":\"代理和昱树脂\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"和昱树脂\"},{\"CUSTTRADEID\":\"0025210100013061\",\"INNERCLIENTID\":\"0000000012\",\"USERCODE\":\"_ST_0000000012\",\"CLIENTABBR\":\"代理上杭鸿阳\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"上杭鸿阳\"},{\"CUSTTRADEID\":\"0025210100015973\",\"INNERCLIENTID\":\"0000000013\",\"USERCODE\":\"_ST_0000000013\",\"CLIENTABBR\":\"代理上杭万祥\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"上杭万祥\"},{\"CUSTTRADEID\":\"0025210100017436\",\"INNERCLIENTID\":\"0000000014\",\"USERCODE\":\"_ST_0000000014\",\"CLIENTABBR\":\"代理正龙金矿\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"正龙金矿\"},{\"CUSTTRADEID\":\"0025210100018932\",\"INNERCLIENTID\":\"0000000015\",\"USERCODE\":\"_ST_0000000015\",\"CLIENTABBR\":\"代理金山黄金\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"金山黄金\"},{\"CUSTTRADEID\":\"0025210100019270\",\"INNERCLIENTID\":\"0000000016\",\"USERCODE\":\"_ST_0000000016\",\"CLIENTABBR\":\"代理曙光化工\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"曙光化工\"},{\"CUSTTRADEID\":\"0025210100023747\",\"INNERCLIENTID\":\"0000000017\",\"USERCODE\":\"_ST_0000000017\",\"CLIENTABBR\":\"代理凯韦投资\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"凯韦投资\"},{\"CUSTTRADEID\":\"0025210100024704\",\"INNERCLIENTID\":\"0000000018\",\"USERCODE\":\"_ST_0000000018\",\"CLIENTABBR\":\"代理紫金矿冶\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"紫金矿冶\"},{\"CUSTTRADEID\":\"0025210100024861\",\"INNERCLIENTID\":\"0000000019\",\"USERCODE\":\"_ST_0000000019\",\"CLIENTABBR\":\"代理石狮新成\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"石狮新成\"},{\"CUSTTRADEID\":\"0025210100025581\",\"INNERCLIENTID\":\"0000000020\",\"USERCODE\":\"_ST_0000000020\",\"CLIENTABBR\":\"代理紫金投资\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"紫金投资\"},{\"CUSTTRADEID\":\"0025210100027763\",\"INNERCLIENTID\":\"0000000021\",\"USERCODE\":\"_ST_0000000021\",\"CLIENTABBR\":\"代理梅州海鑫\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"梅州海鑫\"},{\"CUSTTRADEID\":\"0025210100032488\",\"INNERCLIENTID\":\"0000000022\",\"USERCODE\":\"_ST_0000000022\",\"CLIENTABBR\":\"代理龙岩金鼎象\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"龙岩金鼎象\"},{\"CUSTTRADEID\":\"0025210100032602\",\"INNERCLIENTID\":\"0000000023\",\"USERCODE\":\"_ST_0000000023\",\"CLIENTABBR\":\"代理信宜东坑\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"信宜东坑\"},{\"CUSTTRADEID\":\"0025210100033074\",\"INNERCLIENTID\":\"0000000024\",\"USERCODE\":\"_ST_0000000024\",\"CLIENTABBR\":\"代理深圳名象\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"深圳名象\"},{\"CUSTTRADEID\":\"0025210100034008\",\"INNERCLIENTID\":\"0000000025\",\"USERCODE\":\"_ST_0000000025\",\"CLIENTABBR\":\"代理龙岩兴隆鑫\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"龙岩兴隆鑫\"},{\"CUSTTRADEID\":\"0025210100035740\",\"INNERCLIENTID\":\"0000000026\",\"USERCODE\":\"_ST_0000000026\",\"CLIENTABBR\":\"代理龙岩鑫晖\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"龙岩鑫晖\"},{\"CUSTTRADEID\":\"0025210100037876\",\"INNERCLIENTID\":\"0000000027\",\"USERCODE\":\"_ST_0000000027\",\"CLIENTABBR\":\"代理厦门敦豪\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"厦门敦豪\"},{\"CUSTTRADEID\":\"0025210100037887\",\"INNERCLIENTID\":\"0000000028\",\"USERCODE\":\"_ST_0000000028\",\"CLIENTABBR\":\"代理永安格力\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"永安格力\"},{\"CUSTTRADEID\":\"0025210100038057\",\"INNERCLIENTID\":\"0000000029\",\"USERCODE\":\"_ST_0000000029\",\"CLIENTABBR\":\"代理厦门广颐\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"厦门广颐\"},{\"CUSTTRADEID\":\"0025210100038271\",\"INNERCLIENTID\":\"0000000030\",\"USERCODE\":\"_ST_0000000030\",\"CLIENTABBR\":\"代理顺裕公司\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"顺裕公司\"},{\"CUSTTRADEID\":\"0025210100038417\",\"INNERCLIENTID\":\"0000000031\",\"USERCODE\":\"_ST_0000000031\",\"CLIENTABBR\":\"代理厦门速帆\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"厦门速帆\"},{\"CUSTTRADEID\":\"0025210100038518\",\"INNERCLIENTID\":\"0000000032\",\"USERCODE\":\"_ST_0000000032\",\"CLIENTABBR\":\"代理龙岩天利\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"龙岩天利\"},{\"CUSTTRADEID\":\"0025210100041309\",\"INNERCLIENTID\":\"0000000033\",\"USERCODE\":\"_ST_0000000033\",\"CLIENTABBR\":\"代理龙岩顺裕\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"龙岩顺裕\"},{\"CUSTTRADEID\":\"0025210100041781\",\"INNERCLIENTID\":\"0000000034\",\"USERCODE\":\"_ST_0000000034\",\"CLIENTABBR\":\"代理元阳华西\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"元阳华西\"},{\"CUSTTRADEID\":\"0025210100051197\",\"INNERCLIENTID\":\"0000000035\",\"USERCODE\":\"_ST_0000000035\",\"CLIENTABBR\":\"代理丘北拓岩\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"丘北拓岩\"},{\"CUSTTRADEID\":\"0025210100055124\",\"INNERCLIENTID\":\"0000000036\",\"USERCODE\":\"_ST_0000000036\",\"CLIENTABBR\":\"代理上杭威特\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"上杭威特\"},{\"CUSTTRADEID\":\"0025210100055966\",\"INNERCLIENTID\":\"0000000037\",\"USERCODE\":\"_ST_0000000037\",\"CLIENTABBR\":\"代理龙岩永清\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"龙岩永清\"},{\"CUSTTRADEID\":\"0025210100057306\",\"INNERCLIENTID\":\"0000000038\",\"USERCODE\":\"_ST_0000000038\",\"CLIENTABBR\":\"代理上杭绿之源\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"上杭绿之源\"},{\"CUSTTRADEID\":\"0025210100057317\",\"INNERCLIENTID\":\"0000000039\",\"USERCODE\":\"_ST_0000000039\",\"CLIENTABBR\":\"代理龙岩石壁龙\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"龙岩石壁龙\"},{\"CUSTTRADEID\":\"0025210100060670\",\"INNERCLIENTID\":\"0000000040\",\"USERCODE\":\"_ST_0000000040\",\"CLIENTABBR\":\"代理龙岩鼎鑫\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"龙岩鼎鑫\"},{\"CUSTTRADEID\":\"0025210100074204\",\"INNERCLIENTID\":\"0000000041\",\"USERCODE\":\"_ST_0000000041\",\"CLIENTABBR\":\"代理紫金黄金珠宝\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"紫金矿业集团黄金珠宝有限公司\"},{\"CUSTTRADEID\":\"0025210100078590\",\"INNERCLIENTID\":\"0000000042\",\"USERCODE\":\"_ST_0000000042\",\"CLIENTABBR\":\"代理内蒙金中\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"内蒙金中\"},{\"CUSTTRADEID\":\"0025210100078961\",\"INNERCLIENTID\":\"0000000043\",\"USERCODE\":\"_ST_0000000043\",\"CLIENTABBR\":\"代理紫金铜业\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"紫金铜业\"},{\"CUSTTRADEID\":\"0025210100084070\",\"INNERCLIENTID\":\"0000000044\",\"USERCODE\":\"_ST_0000000044\",\"CLIENTABBR\":\"代理陇南紫金\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"陇南紫金\"},{\"CUSTTRADEID\":\"0025210100091539\",\"INNERCLIENTID\":\"0000000045\",\"USERCODE\":\"_ST_0000000045\",\"CLIENTABBR\":\"代理漳平银丰\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"漳平银丰\"},{\"CUSTTRADEID\":\"0025210100096309\",\"INNERCLIENTID\":\"0000000046\",\"USERCODE\":\"_ST_0000000046\",\"CLIENTABBR\":\"代理贵州西南紫金\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"贵州西南紫金\"},{\"CUSTTRADEID\":\"0025210100123816\",\"INNERCLIENTID\":\"0000000047\",\"USERCODE\":\"_ST_0000000047\",\"CLIENTABBR\":\"代理紫金贸易\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"紫金贸易\"},{\"CUSTTRADEID\":\"0025210100139981\",\"INNERCLIENTID\":\"0000000048\",\"USERCODE\":\"_ST_0000000048\",\"CLIENTABBR\":\"代理紫金环球\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"紫金环球\"},{\"CUSTTRADEID\":\"0025210100146372\",\"INNERCLIENTID\":\"0000000049\",\"USERCODE\":\"_ST_0000000049\",\"CLIENTABBR\":\"代理紫金矿业进口\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"紫金矿业进口\"},{\"CUSTTRADEID\":\"0025210100147025\",\"INNERCLIENTID\":\"0000000050\",\"USERCODE\":\"_ST_0000000050\",\"CLIENTABBR\":\"代理黄金冶炼\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"黄金冶炼\"},{\"CUSTTRADEID\":\"0025210100149421\",\"INNERCLIENTID\":\"0000000051\",\"USERCODE\":\"_ST_0000000051\",\"CLIENTABBR\":\"代理紫金金行\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"紫金金行\"},{\"CUSTTRADEID\":\"0025210100157374\",\"INNERCLIENTID\":\"0000000052\",\"USERCODE\":\"_ST_0000000052\",\"CLIENTABBR\":\"代理厦金宝\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"厦金宝\"},{\"CUSTTRADEID\":\"0025210100165632\",\"INNERCLIENTID\":\"0000000101\",\"USERCODE\":\"_ST_0000000101\",\"CLIENTABBR\":\"代理厦门华万腾\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"厦门华万腾\"},{\"CUSTTRADEID\":\"0025210100184868\",\"INNERCLIENTID\":\"0000000121\",\"USERCODE\":\"_ST_0000000121\",\"CLIENTABBR\":\"代理福建紫金贵金属材料有限公司\",\"SEATID\":\"002521\",\"CLIENTNAME\":\"福建紫金贵金属材料有限公司\"}]}";
+        byte[] bytes = str.getBytes(Util.GBK);
+        System.out.println(bytes.length);
+    }
+
+    static void printInputStream(String clazz) {
+        try {
+            String      name  = clazz.replace(".", "/") + ".class";
+            InputStream is    = Test7.class.getClassLoader().getResourceAsStream(name);
+            int         len   = is.available();
+            byte[]      bb    = new byte[len];
+            int         r_len = 0;
+            for (; r_len != len; ) {
+                r_len += is.read(bb, r_len, len - r_len);
+            }
+            System.out.println(clazz + ">>" + Base64.getEncoder().encodeToString(bb));
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+}
diff --git a/firenio-test/src/main/java/test/io/Test8.java b/firenio-test/src/main/java/test/io/Test8.java
new file mode 100644
index 000000000..234c08533
--- /dev/null
+++ b/firenio-test/src/main/java/test/io/Test8.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.io;
+
+import java.util.Arrays;
+
+import com.firenio.common.ByteUtil;
+import com.firenio.common.Util;
+
+/**
+ * @author: wangkai
+ **/
+public class Test8 {
+
+    public static void main(String[] args) {
+
+        int    count = 10;
+        byte[] data  = new byte[1024 * 1024 * 1024];
+
+        //        for (int i = 0; i < data.length; i++) {
+        //            data[i] = (byte) i;
+        //        }
+
+        Arrays.fill(data, (byte) 1);
+
+        long start = System.nanoTime();
+
+        long res = test_normal(data, count);
+
+        long past = System.nanoTime() - start;
+
+        System.out.println("res: " + res);
+
+        System.out.println("past: " + (past / 1000_1000));
+
+    }
+
+
+    static long test_normal(byte[] data, int count) {
+        long sum = 0;
+        for (int i = 0; i < count; i++) {
+            for (int j = 0; j < data.length; j++) {
+                sum += data[j];
+            }
+        }
+        return sum;
+    }
+
+
+    static long test_exp(byte[] data, int count) {
+        long sum1 = 0;
+        long sum2 = 0;
+        long sum3 = 0;
+        long sum4 = 0;
+        for (int i = 0; i < count; i++) {
+            for (int j = 0; j < data.length; j += 4) {
+                sum1 += data[j];
+                sum2 += data[j + 1];
+                sum3 += data[j + 2];
+                sum4 += data[j + 3];
+            }
+        }
+        return sum1 + sum2 + sum3 + sum4;
+    }
+
+}
diff --git a/firenio-test/src/main/java/test/io/TestByteBufSkip.java b/firenio-test/src/main/java/test/io/TestByteBufSkip.java
new file mode 100644
index 000000000..d708ba2b5
--- /dev/null
+++ b/firenio-test/src/main/java/test/io/TestByteBufSkip.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.io;
+
+
+import com.firenio.log.LoggerFactory;
+
+/**
+ * @author: wangkai
+ **/
+public class TestByteBufSkip {
+
+    public static void main(String[] args) {
+
+        LoggerFactory.setEnableSLF4JLogger(false);
+
+        test_firenio();
+        test_netty();
+
+    }
+
+    static void test_firenio() {
+        com.firenio.buffer.ByteBuf out = com.firenio.buffer.ByteBuf.buffer(100);
+
+        int write_index = out.writeIndex();
+        out.skipWrite(4);
+        out.writeInt(100);
+        out.writeInt(200);
+        out.setInt(write_index, out.readableBytes() - 4);
+
+        System.out.println("firenio: ");
+        System.out.println(out.readInt());
+        System.out.println(out.readInt());
+        System.out.println(out.readInt());
+
+
+    }
+
+
+    static void test_netty() {
+
+        io.netty.buffer.ByteBuf out = io.netty.buffer.Unpooled.buffer();
+
+        int writerIndex = out.writerIndex();
+        out.writerIndex(out.writerIndex() + 4);
+        out.writeInt(100);
+        out.writeInt(200);
+        out.setInt(writerIndex, out.readableBytes() - 4);
+
+        System.out.println("netty: ");
+        System.out.println(out.readInt());
+        System.out.println(out.readInt());
+        System.out.println(out.readInt());
+
+    }
+
+
+}
diff --git a/firenio-test/src/main/java/test/io/TestDio.java b/firenio-test/src/main/java/test/io/TestDio.java
new file mode 100644
index 000000000..497319f89
--- /dev/null
+++ b/firenio-test/src/main/java/test/io/TestDio.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.io;
+
+import com.firenio.DevelopConfig;
+import com.firenio.common.Unsafe;
+import com.firenio.component.Native;
+import com.firenio.log.LoggerFactory;
+
+/**
+ * @program: firenio
+ * @description:
+ * @author: wangkai
+ * @create: 2019-09-11 16:18
+ **/
+public class TestDio {
+
+    static {
+        LoggerFactory.setEnableSLF4JLogger(false);
+        DevelopConfig.EPOLL_DEBUG = true;
+        DevelopConfig.NATIVE_DEBUG = true;
+    }
+
+    static final int PS = 1024 * 4;
+
+    static final String path = "/home/test/temp/test_direct2.txt";
+
+    public static void main(String[] args) throws Exception {
+
+        test_direct_write();
+        test_direct_read();
+    }
+
+    static void test_direct_write() {
+        long address = Native.posix_memalign_allocate(PS, PS);
+        int  fd      = Native.open(path, Native.O_WRONLY | Native.O_CREAT | Native.O_DIRECT | Native.O_TRUNC, 0755);
+        System.out.println("file len: " + Native.file_length(fd));
+        byte[] data = "hello world!0".getBytes();
+        do_write_data(fd, address, data, 0);
+        do_write_data(fd, address, data, 1);
+        do_write_data(fd, address, data, 2);
+        do_write_data(fd, address, data, 3);
+        System.out.println("file len: " + Native.file_length(fd));
+        Unsafe.free(address);
+        Native.close(fd);
+    }
+
+    static void do_write_data(int fd, long address, byte[] data, int index) {
+        data[data.length - 1] = (byte) (index);
+        Unsafe.copyFromArray(data, 0, address, data.length);
+        if (index > 0) {
+            Native.pwrite(fd, address, PS, index * PS);
+        } else {
+            Native.write(fd, address, PS);
+        }
+
+    }
+
+    static void test_direct_read() {
+        long   address  = Native.posix_memalign_allocate(PS, PS);
+        int    fd       = Native.open(path, Native.O_RDONLY | Native.O_CREAT | Native.O_DIRECT, 0755);
+        long   file_len = Native.file_length(fd);
+        byte[] data     = new byte[16];
+        System.out.println("file len: " + file_len);
+        Native.lseek(fd, file_len, Native.SEEK_SET);
+        do_read_data(fd, address, data, 0);
+        do_read_data(fd, address, data, PS * 2);
+        Unsafe.free(address);
+        Native.close(fd);
+    }
+
+    static void do_read_data(int fd, long address, byte[] data, long pos) {
+        int read;
+        if (pos == 0) {
+            Native.lseek(fd, pos, Native.SEEK_SET);
+            read = Native.read(fd, address, PS);
+        } else {
+            read = Native.pread(fd, address, PS, pos);
+        }
+        System.out.println("read len: " + read);
+        Unsafe.copyToArray(address, data, 0, 16);
+        String content = new String(data);
+        System.out.println("content: " + content);
+
+    }
+
+}
diff --git a/firenio-test/src/main/java/test/io/TestFloat.java b/firenio-test/src/main/java/test/io/TestFloat.java
new file mode 100644
index 000000000..d3efd84d4
--- /dev/null
+++ b/firenio-test/src/main/java/test/io/TestFloat.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.io;
+
+import com.firenio.buffer.ByteBuf;
+import com.firenio.common.ByteUtil;
+
+/**
+ * @author: wangkai
+ **/
+public class TestFloat {
+
+    public static void main(String[] args) {
+        System.out.println("2.03f: " + Float.floatToIntBits(2.03f));
+        System.out.println("0.5f: " + Float.floatToIntBits(0.5f));
+        System.out.println("0.9f: " + Float.floatToIntBits(0.9f));
+        System.out.println("1.0f: " + Float.floatToIntBits(1.0f));
+        System.out.println("12.34f: " + Float.floatToIntBits(12.34f));
+        System.out.println("1.5f: " + Float.floatToIntBits(1.5f));
+        System.out.println("0.1f: " + Float.floatToIntBits(1f - 0.9f));
+        System.out.println(1 - 0.9f);
+        System.out.println(1f + 0.5f);
+
+        int v = 0b00111101100010011001100110011010;
+        System.out.println(v);
+
+        long l = 34;
+        for (int i = 0; i < 23; i++) {
+            l *= 2;
+        }
+        System.out.println(l);
+
+        float f2 = 0.01f;
+        float f3 = f2 + 1;
+        for (int i = 0; i < 999999; i++) {
+            f3 += f2;
+            int f4 = Float.floatToIntBits(f3);
+            if ((f4 & 1) == 1) {
+                System.out.println(f3 + "------ & 1 =====1");
+                break;
+            }
+        }
+        System.out.println("end...");
+
+    }
+}
diff --git a/firenio-test/src/main/java/test/io/TestJDKBug1.java b/firenio-test/src/main/java/test/io/TestJDKBug1.java
new file mode 100644
index 000000000..7b0d02d35
--- /dev/null
+++ b/firenio-test/src/main/java/test/io/TestJDKBug1.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.io;
+
+/**
+ * @author: wangkai
+ **/
+public class TestJDKBug1 {
+
+    public void test() {
+        int i = -1;
+//        while ((i -= 3) > 0);
+        System.out.println("i = " + i);
+    }
+
+    public static void main(String[] args) {
+        TestJDKBug1 hello = new TestJDKBug1();
+        for (int i = 0; i < 50_000; i++) {
+            hello.test();
+        }
+    }
+
+
+
+}
diff --git a/firenio-test/src/main/java/test/io/TestLoad.java b/firenio-test/src/main/java/test/io/TestLoad.java
new file mode 100644
index 000000000..25a6effc0
--- /dev/null
+++ b/firenio-test/src/main/java/test/io/TestLoad.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.io;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.elasticsearch.common.recycler.Recycler.C;
+
+import com.firenio.common.FileUtil;
+
+/**
+ * @author: wangkai
+ **/
+public class TestLoad {
+
+    public static void main(String[] args) throws Exception {
+
+        String s_128_0   = "1280141.0028337";
+        String s_128_1   = "1281063.0028301";
+        String s_128_930 = "1289307.0028297";
+        String s_128_938 = "1289385.0028258";
+        String s_130_0   = "1300290.0028466";
+        String s_130_2   = "1302952.0028294";
+        cal(s_128_0);
+        cal(s_128_1);
+        cal(s_128_930);
+        cal(s_128_938);
+        cal(s_130_0);
+        cal(s_130_2);
+
+    }
+
+
+    static void cal(String dic) throws Exception {
+        int  count  = 10;
+        File s_file = new File("C:\\Users\\wangkai\\Downloads\\" + dic + "\\z-small.txt");
+        File m_file = new File("C:\\Users\\wangkai\\Downloads\\" + dic + "\\z-medium.txt");
+        File l_file = new File("C:\\Users\\wangkai\\Downloads\\" + dic + "\\z-large.txt");
+
+        List s_c = getQPS(s_file, count, 0);
+        List m_c = getQPS(m_file, count, 1);
+        List l_c = getQPS(l_file, count, 2);
+
+        int[]         abs_cnt = new int[3];
+        double        abs_cut = 0;
+        double        abs_sum = 0;
+        List max_con = new ArrayList<>();
+        List max_qps = new ArrayList<>(count);
+        List     temp    = new ArrayList<>(3);
+
+        for (int i = 0; i < count; i++) {
+            temp.clear();
+            temp.add(s_c.get(i));
+            temp.add(m_c.get(i));
+            temp.add(l_c.get(i));
+            Collections.sort(temp, new Comparator() {
+                @Override
+                public int compare(Cfg o1, Cfg o2) {
+                    return (int) ((o1.rtt * 100) - (o2.rtt * 100));
+                }
+            });
+            double qps   = 0;
+            int    r_con = 1024;
+            for (int j = 0; j < temp.size(); j++) {
+                Cfg    c    = temp.get(j);
+                double _qps = (Math.min(r_con, c.con) * (1000 / c.rtt));
+                qps += _qps;
+                r_con -= c.con;
+                c.qps = _qps;
+                abs_cnt[c.type] += _qps;
+            }
+            abs_sum += qps * 6;
+            max_qps.add((int) qps);
+
+            int    base  = 1900;
+            double s_qps = s_c.get(i).qps;
+            double m_qps = m_c.get(i).qps;
+            double l_qps = l_c.get(i).qps;
+            double a_qps = s_qps + m_qps + l_qps;
+            if (s_qps - (a_qps * 1 / 6) > 0) {
+                abs_cut += (s_qps - (a_qps * 1 / 6));
+                //                abs_cut += (s_qps - (a_qps * 1 / 6)) / (a_qps * 1 / 6);
+            }
+            if (m_qps - (a_qps * 2 / 6) > 0) {
+                abs_cut += (m_qps - (a_qps * 2 / 6));
+                //                abs_cut += (m_qps - (a_qps * 2 / 6)) / (a_qps * 2 / 6);
+            }
+            if (l_qps - (a_qps * 3 / 6) > 0) {
+                abs_cut += (l_qps - (a_qps * 3 / 6));
+                //                abs_cut += (l_qps - (a_qps * 3 / 6)) / (a_qps * 3 / 6);
+            }
+            max_con.add(s_c.get(i).con + m_c.get(i).con + l_c.get(i).con);
+        }
+        System.out.println("abs_sum:" + abs_sum);
+        System.out.println("sc:" + s_c);
+        System.out.println("mc:" + m_c);
+        System.out.println("lc:" + l_c);
+        System.out.println("ac:" + max_qps);
+        System.out.println("max_con: " + max_con);
+        System.out.println("abs_cut: " + abs_cut);
+        System.out.println(dic + ">>abs_cnt: " + (abs_cnt[0] + abs_cnt[1] + abs_cnt[2]) + ",abs_cnt_s:" + abs_cnt[0] + ",abs_cnt_m:" + abs_cnt[1] + ",abs_cnt_l:" + abs_cnt[2]);
+        System.out.println();
+    }
+
+    static int mask(double q, double v, double base) {
+        if (q < base) {
+            return (int) v;
+        }
+        return (int) (v * (1 + (((q - base) / base) * ((q - base) / base))));
+    }
+
+    static List getQPS(File file, int count, int type) throws Exception {
+        List ss  = FileUtil.readLines(file);
+        List    res = new ArrayList<>(count);
+        for (int i = 0; i < count; i++) {
+            String s               = ss.get(i);
+            int    avg_rtt_idx     = s.indexOf("avg_rtt") + 8;
+            int    avg_rtt_idx_end = s.indexOf(',', avg_rtt_idx);
+            int    c               = Integer.parseInt(s.substring(s.length() - 3));
+            double rtt             = Double.parseDouble(s.substring(avg_rtt_idx, avg_rtt_idx_end));
+            if (c < 100 || c > 650 || rtt < 10 || rtt > 100) {
+                System.out.println("error");
+            }
+            Cfg cfg = new Cfg();
+            cfg.con = c;
+            cfg.rtt = rtt;
+            cfg.type = type;
+            res.add(cfg);
+        }
+        return res;
+    }
+
+    static class Cfg {
+
+        double rtt;
+        int    con;
+        int    type;
+        double qps;
+
+        @Override
+        public String toString() {
+            return String.valueOf((int)qps);
+        }
+    }
+
+
+}
diff --git a/firenio-test/src/main/java/test/io/TestLoad1.java b/firenio-test/src/main/java/test/io/TestLoad1.java
new file mode 100644
index 000000000..8ffd8084f
--- /dev/null
+++ b/firenio-test/src/main/java/test/io/TestLoad1.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.io;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import com.firenio.common.Cryptos;
+import com.firenio.common.FileUtil;
+
+/**
+ * @author: wangkai
+ **/
+public class TestLoad1 {
+
+
+    public static void main(String[] args) throws Exception {
+
+        double dd = 10.55d;
+        int aa = (int)dd;
+        System.out.println(aa);
+
+        String clazz = "yv66vgAAADQAYQoAGAA3CQANADgJAA0AOQcAOgoABAA7CQANADwHAD0LAD4APwoABwA7CwA+AEALAEEAQgsAQQBDBwBECgANAEULAD4ARgcARwoAEAA3CABICgAQAEkKABAASggASwoAEABMCgAQAE0HAE4BAA5tYXhfY29uY3VycmVudAEAAUkBAAdhdmdfcnR0AQABRAEABnBlcm1pdAEAIExqYXZhL3V0aWwvY29uY3VycmVudC9TZW1hcGhvcmU7AQAGPGluaXQ+AQAFKElEKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAIkxjb20vYWxpd2FyZS90aWFuY2hpL1Byb3ZpZGVyQ29uZjsBAAdjb252ZXJ0AQAiKExqYXZhL3V0aWwvTGlzdDspTGphdmEvdXRpbC9MaXN0OwEADHByb3ZpZGVyQ29uZgEAB2NvbmZpZ3MBABBMamF2YS91dGlsL0xpc3Q7AQAEY29uZgEAFkxvY2FsVmFyaWFibGVUeXBlVGFibGUBADRMamF2YS91dGlsL0xpc3Q8TGNvbS9hbGl3YXJlL3RpYW5jaGkvUHJvdmlkZXJDb25mOz47AQANU3RhY2tNYXBUYWJsZQcATwcAUAEACVNpZ25hdHVyZQEAaihMamF2YS91dGlsL0xpc3Q8TGNvbS9hbGl3YXJlL3RpYW5jaGkvUHJvdmlkZXJDb25mOz47KUxqYXZhL3V0aWwvTGlzdDxMY29tL2FsaXdhcmUvdGlhbmNoaS9Qcm92aWRlckNvbmY7PjsBAAh0b1N0cmluZwEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAKU291cmNlRmlsZQEAEVByb3ZpZGVyQ29uZi5qYXZhDAAfAFEMABkAGgwAGwAcAQAeamF2YS91dGlsL2NvbmN1cnJlbnQvU2VtYXBob3JlDAAfAFIMAB0AHgEAE2phdmEvdXRpbC9BcnJheUxpc3QHAE8MAFMAVAwAVQBWBwBQDABXAFgMAFkAWgEAIGNvbS9hbGl3YXJlL3RpYW5jaGkvUHJvdmlkZXJDb25mDAAfACAMAFsAXAEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyAQAOY29uZjogYXZnX3J0dDoMAF0AXgwAXQBfAQARLCBtYXhfY29uY3VycmVudDoMAF0AYAwAMwA0AQAQamF2YS9sYW5nL09iamVjdAEADmphdmEvdXRpbC9MaXN0AQASamF2YS91dGlsL0l0ZXJhdG9yAQADKClWAQAEKEkpVgEABHNpemUBAAMoKUkBAAhpdGVyYXRvcgEAFigpTGphdmEvdXRpbC9JdGVyYXRvcjsBAAdoYXNOZXh0AQADKClaAQAEbmV4dAEAFCgpTGphdmEvbGFuZy9PYmplY3Q7AQADYWRkAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaAQAGYXBwZW5kAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZ0J1aWxkZXI7AQAcKEQpTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEAHChJKUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsAIQANABgAAAADABEAGQAaAAAAEQAbABwAAAARAB0AHgAAAAMAAQAfACAAAQAhAAAAaQAEAAQAAAAbKrcAASobtQACKii1AAMquwAEWRu3AAW1AAaxAAAAAgAiAAAAFgAFAAAADwAEABAACQARAA4AEgAaABMAIwAAACAAAwAAABsAJAAlAAAAAAAbABkAGgABAAAAGwAbABwAAgAJACYAJwACACEAAADBAAYABAAAAEO7AAdZKrkACAEAtwAJTCq5AAoBAE0suQALAQCZACYsuQAMAQDAAA1OK7sADVkttAACLbQAA7cADrkADwIAV6f/1yuwAAAABAAiAAAAFgAFAAAAFgAOABcAKAAYAD4AGQBBABoAIwAAACAAAwAoABYAKAAlAAMAAABDACkAKgAAAA4ANQArACoAAQAsAAAAFgACAAAAQwApAC0AAAAOADUAKwAtAAEALgAAAA4AAv0AFQcALwcAMPoAKwAxAAAAAgAyAAEAMwA0AAEAIQAAAE0AAwABAAAAI7sAEFm3ABESErYAEyq0AAO2ABQSFbYAEyq0AAK2ABa2ABewAAAAAgAiAAAABgABAAAAHwAjAAAADAABAAAAIwAkACUAAAABADUAAAACADY=";
+
+        FileUtil.writeByFile(new File("C://temp/a.class"), Cryptos.base64_de(clazz));
+
+
+    }
+
+
+}
diff --git a/firenio-test/src/main/java/test/io/TestMMap.java b/firenio-test/src/main/java/test/io/TestMMap.java
new file mode 100644
index 000000000..bc2f7bb79
--- /dev/null
+++ b/firenio-test/src/main/java/test/io/TestMMap.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.io;
+
+import java.io.File;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileChannel.MapMode;
+import java.nio.file.OpenOption;
+import java.nio.file.StandardOpenOption;
+
+import com.firenio.common.Unsafe;
+
+/**
+ * @author: wangkai
+ **/
+public class TestMMap {
+
+    static OpenOption[] FC_OPS = new OpenOption[]{StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING};
+
+    public static void main(String[] args) throws Exception {
+        File             file1 = new File("C://temp/test_mmap1.txt");
+        File             file2 = new File("C://temp/test_mmap2.txt");
+        FileChannel      ch1   = FileChannel.open(file1.toPath(), FC_OPS);
+        FileChannel      ch2   = FileChannel.open(file2.toPath(), FC_OPS);
+        MappedByteBuffer buf1  = ch1.map(MapMode.READ_WRITE, 0, 32);
+        MappedByteBuffer buf2  = ch2.map(MapMode.READ_WRITE, 0, 32);
+        byte[]           data  = "abc123456".getBytes();
+        buf1.put(data);
+        buf1.put((byte) 1);
+        buf1.put((byte) 2);
+        buf1.put((byte) 3);
+        buf1.put((byte) 4);
+        Unsafe.copyFromArray(data, 0, Unsafe.address(buf2), data.length);
+        Unsafe.copyFromArray(data, 0, Unsafe.address(buf1) + 15, data.length);
+        Unsafe.copyFromArray(data, 0, Unsafe.address(buf2) + 15, data.length);
+        System.out.println("finish...");
+        System.exit(0);
+    }
+
+
+}
diff --git a/firenio-test/src/main/java/test/io/TestMulticastSocket.java b/firenio-test/src/main/java/test/io/TestMulticastSocket.java
new file mode 100644
index 000000000..9f8806430
--- /dev/null
+++ b/firenio-test/src/main/java/test/io/TestMulticastSocket.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.io;
+
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+import java.net.MulticastSocket;
+
+/**
+ * @program: firenio
+ * @description:
+ * @author: wangkai
+ * @create: 2019-05-22 16:21
+ **/
+public class TestMulticastSocket {
+
+
+    public static void main(String[] args) throws Exception {
+
+        System.out.println(1f - 9.0 / 10);
+
+
+    }
+
+
+}
diff --git a/firenio-test/src/main/java/test/io/buffer/TestByteBufCopy.java b/firenio-test/src/main/java/test/io/buffer/TestByteBufCopy.java
index b3d5b3993..c98a3d471 100644
--- a/firenio-test/src/main/java/test/io/buffer/TestByteBufCopy.java
+++ b/firenio-test/src/main/java/test/io/buffer/TestByteBufCopy.java
@@ -17,22 +17,27 @@
 
 import java.lang.reflect.Method;
 import java.nio.ByteBuffer;
+import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;
 
 import org.junit.Test;
 
 import com.firenio.buffer.ByteBuf;
+import com.firenio.common.Assert;
 import com.firenio.common.Unsafe;
 import com.firenio.common.Util;
-
-import junit.framework.Assert;
+import com.firenio.log.LoggerFactory;
 
 /**
  * @author wangkai
  */
 public class TestByteBufCopy {
 
+    static {
+        LoggerFactory.setEnableSLF4JLogger(false);
+    }
+
     static final byte[]     _data = "abc123abc123".getBytes();
     static final ByteBuf    arrayData;
     static final ByteBuf    directData;
@@ -44,16 +49,16 @@ public class TestByteBufCopy {
         jDirectData = Unsafe.allocateDirectByteBuffer(12);
         jArrayData.position(6);
         jDirectData.put(_data).position(6);
-        arrayData = ByteBuf.wrap(jArrayData).skip(6);
-        directData = ByteBuf.wrap(jDirectData).skip(6);
+        arrayData = ByteBuf.wrap(jArrayData).skipWrite(6);
+        directData = ByteBuf.wrap(jDirectData).skipWrite(6);
     }
 
     static ByteBuf _array() {
-        return ByteBuf.heap(12).position(6);
+        return ByteBuf.heap(12).writeIndex(6);
     }
 
     static ByteBuf _direct() {
-        return ByteBuf.direct(12).position(6);
+        return ByteBuf.direct(12).writeIndex(6);
     }
 
     static ByteBuffer _jArray() {
@@ -65,11 +70,11 @@ static ByteBuffer _jDirect() {
     }
 
     static ByteBuf arrayData() {
-        return arrayData.limit(12).position(6);
+        return arrayData.writeIndex(12).readIndex(6);
     }
 
     static ByteBuf directData() {
-        return directData.limit(12).position(6);
+        return directData.writeIndex(12).readIndex(6);
     }
 
     static ByteBuffer jArrayData() {
@@ -83,16 +88,11 @@ static ByteBuffer jDirectData() {
     }
 
     void _invoke(Method m) throws Exception {
-        String name = m.getName();
-        if (name == null) {
-            System.out.println();
-        }
         Object res = m.invoke(this, (Object[]) null);
         byte[] bytes;
         if (res instanceof ByteBuf) {
-            ((ByteBuf) res).flip();
-            ((ByteBuf) res).position(((ByteBuf) res).limit() - 6);
-            bytes = ((ByteBuf) res).getBytes();
+            ((ByteBuf) res).readIndex(((ByteBuf) res).writeIndex() - 6);
+            bytes = ((ByteBuf) res).readBytes();
         } else if (res instanceof ByteBuffer) {
             ((ByteBuffer) res).flip();
             ((ByteBuffer) res).position(((ByteBuffer) res).limit() - 6);
@@ -101,7 +101,7 @@ void _invoke(Method m) throws Exception {
         } else {
             bytes = "1".getBytes();
         }
-        Assert.assertEquals("abc123", new String(bytes));
+        Assert.expectEquals("abc123", new String(bytes));
     }
 
     @Test
@@ -109,7 +109,7 @@ void _invoke(Method m) throws Exception {
     public void _testAll() throws Exception {
 
         Method[]     ms   = TestByteBufCopy.class.getDeclaredMethods();
-        List list = Util.array2List(ms);
+        List list = Arrays.asList(ms);
         list.sort(Comparator.comparing(Method::getName));
 
         for (int i = 0; i < list.size(); i++) {
@@ -126,97 +126,97 @@ public void _testAll() throws Exception {
 
     Object arrayGetArray() {
         ByteBuf buf = _array();
-        arrayData().getBytes(buf);
+        arrayData().readBytes(buf);
         return buf;
     }
 
     Object arrayGetDirect() {
         ByteBuf buf = _direct();
-        arrayData().getBytes(buf);
+        arrayData().readBytes(buf);
         return buf;
     }
 
     Object arrayGetJArray() {
         ByteBuffer buf = _jArray();
-        arrayData().getBytes(buf);
+        arrayData().readBytes(buf);
         return buf;
     }
 
     Object arrayGetJDirect() {
         ByteBuffer buf = _jDirect();
-        arrayData().getBytes(buf);
+        arrayData().readBytes(buf);
         return buf;
     }
 
     Object arrayPutArray() {
         ByteBuf buf = _array();
-        buf.putBytes(arrayData());
+        buf.writeBytes(arrayData());
         return buf;
     }
 
     Object arrayPutDirect() {
         ByteBuf buf = _array();
-        buf.putBytes(directData());
+        buf.writeBytes(directData());
         return buf;
     }
 
     Object arrayPutJArray() {
         ByteBuf buf = _array();
-        buf.putBytes(jArrayData());
+        buf.writeBytes(jArrayData());
         return buf;
     }
 
     Object arrayPutJDirect() {
         ByteBuf buf = _array();
-        buf.putBytes(jDirectData());
+        buf.writeBytes(jDirectData());
         return buf;
     }
 
     Object directGetArray() {
         ByteBuf buf = _array();
-        directData().getBytes(buf);
+        directData().readBytes(buf);
         return buf;
     }
 
     Object directGetDirect() {
         ByteBuf buf = _direct();
-        directData().getBytes(buf);
+        directData().readBytes(buf);
         return buf;
     }
 
     Object directGetJArray() {
         ByteBuffer buf = _jArray();
-        directData().getBytes(buf);
+        directData().readBytes(buf);
         return buf;
     }
 
     Object directGetJDirect() {
         ByteBuffer buf = _jDirect();
-        directData().getBytes(buf);
+        directData().readBytes(buf);
         return buf;
     }
 
     Object directPutArray() {
         ByteBuf buf = _direct();
-        buf.putBytes(arrayData());
+        buf.writeBytes(arrayData());
         return buf;
     }
 
     Object directPutDirect() {
         ByteBuf buf = _direct();
-        buf.putBytes(directData());
+        buf.writeBytes(directData());
         return buf;
     }
 
     Object directPutJArray() {
         ByteBuf buf = _direct();
-        buf.putBytes(jArrayData());
+        buf.writeBytes(jArrayData());
         return buf;
     }
 
     Object directPutJDirect() {
         ByteBuf buf = _direct();
-        buf.putBytes(jDirectData());
+        buf.writeBytes(jDirectData());
         return buf;
     }
 
diff --git a/firenio-test/src/main/java/test/io/buffer/TestBytebufAllocator.java b/firenio-test/src/main/java/test/io/buffer/TestBytebufAllocator.java
index eacbc503f..7d58fd71b 100644
--- a/firenio-test/src/main/java/test/io/buffer/TestBytebufAllocator.java
+++ b/firenio-test/src/main/java/test/io/buffer/TestBytebufAllocator.java
@@ -18,28 +18,31 @@
 import org.junit.Test;
 
 import com.firenio.buffer.ByteBuf;
+import com.firenio.common.Assert;
+import com.firenio.log.LoggerFactory;
 
-import junit.framework.Assert;
 
 public class TestBytebufAllocator {
 
+    static {
+        LoggerFactory.setEnableSLF4JLogger(false);
+    }
+
     static final String data  = "hello;hello;";
     static final String data1 = "hello;";
 
     static void v(ByteBuf buf) {
-        byte[] res = buf.getBytes();
-        Assert.assertEquals(new String(res), data);
+        byte[] res = buf.readBytes();
+        Assert.expectEquals(new String(res), data);
     }
 
     @Test
     public void testput0() {
         ByteBuf src = ByteBuf.direct(1024);
-        src.putBytes(data.getBytes());
-        src.flip();
+        src.writeBytes(data.getBytes());
 
         ByteBuf dst = ByteBuf.direct(1024);
-        dst.putBytes(src);
-        dst.flip();
+        dst.writeBytes(src);
         v(dst);
     }
 
@@ -47,84 +50,83 @@ public void testput0() {
     public void testput1() {
 
         ByteBuf src = ByteBuf.direct(1024);
-        src.putBytes(data.getBytes());
-        src.flip();
+        src.writeBytes(data.getBytes());
 
         ByteBuf dst = ByteBuf.direct(data1.length());
-        dst.putBytes(src);
-        dst.flip();
+        dst.writeBytes(src);
+
         v(dst);
     }
 
     @Test
     public void testput2() {
         ByteBuf src = ByteBuf.heap(1024);
-        src.putBytes(data.getBytes());
-        src.flip();
+        src.writeBytes(data.getBytes());
+
 
         ByteBuf dst = ByteBuf.direct(1024);
-        dst.putBytes(src);
-        dst.flip();
+        dst.writeBytes(src);
+
         v(dst);
     }
 
     @Test
     public void testPut3() {
         ByteBuf src = ByteBuf.heap(1024);
-        src.putBytes(data.getBytes());
-        src.flip();
+        src.writeBytes(data.getBytes());
+
 
         ByteBuf dst = ByteBuf.direct(data1.length());
-        dst.putBytes(src);
-        dst.flip();
+        dst.writeBytes(src);
+
         v(dst);
     }
 
     @Test
     public void testPut4() {
         ByteBuf src = ByteBuf.heap(1024);
-        src.putBytes("hello;hello;".getBytes());
-        src.flip();
+        src.writeBytes("hello;hello;".getBytes());
+
 
         ByteBuf dst = ByteBuf.heap(1024);
-        dst.putBytes(src);
-        dst.flip();
+        dst.writeBytes(src);
+
         v(dst);
     }
 
     @Test
     public void testPut5() {
         ByteBuf src = ByteBuf.heap(1024);
-        src.putBytes("hello;hello;".getBytes());
-        src.flip();
+        src.writeBytes("hello;hello;".getBytes());
+
 
         ByteBuf dst = ByteBuf.heap(data1.length());
-        dst.putBytes(src);
-        dst.flip();
+        dst.writeBytes(src);
+
         v(dst);
     }
 
     @Test
     public void testPut6() {
         ByteBuf src = ByteBuf.direct(1024);
-        src.putBytes("hello;hello;".getBytes());
-        src.flip();
+        src.writeBytes("hello;hello;".getBytes());
+
 
         ByteBuf dst = ByteBuf.heap(1024);
-        dst.putBytes(src);
-        dst.flip();
+        dst.writeBytes(src);
+
         v(dst);
     }
 
     @Test
     public void testPut7() {
         ByteBuf src = ByteBuf.direct(1024);
-        src.putBytes("hello;hello;".getBytes());
-        src.flip();
+        src.writeBytes("hello;hello;".getBytes());
+
 
         ByteBuf dst = ByteBuf.heap(data1.length());
-        dst.putBytes(src);
-        dst.flip();
+        dst.writeBytes(src);
+
         v(dst);
     }
 
diff --git a/firenio-test/src/main/java/test/io/buffer/TestDuplicatedByteBuf.java b/firenio-test/src/main/java/test/io/buffer/TestDuplicatedHeapByteBuf.java
similarity index 81%
rename from firenio-test/src/main/java/test/io/buffer/TestDuplicatedByteBuf.java
rename to firenio-test/src/main/java/test/io/buffer/TestDuplicatedHeapByteBuf.java
index b61a2d321..b6c3a42b2 100644
--- a/firenio-test/src/main/java/test/io/buffer/TestDuplicatedByteBuf.java
+++ b/firenio-test/src/main/java/test/io/buffer/TestDuplicatedHeapByteBuf.java
@@ -19,19 +19,18 @@
 
 import com.firenio.buffer.ByteBuf;
 import com.firenio.buffer.ByteBufAllocator;
-
-import junit.framework.Assert;
+import com.firenio.common.Assert;
 
 /**
  * @author wangkai
  */
-public class TestDuplicatedByteBuf {
+public class TestDuplicatedHeapByteBuf {
 
     static final String data = "abcdef";
 
     static void v(ByteBuf buf) {
 
-        Assert.assertEquals(new String(buf.getBytes()), data);
+        Assert.expectEquals(new String(buf.readBytes()), data);
 
     }
 
@@ -39,8 +38,7 @@ static void v(ByteBuf buf) {
     public void testDirect() {
         ByteBuf buf = ByteBuf.direct(16);
 
-        buf.putBytes(data.getBytes());
-        buf.flip();
+        buf.writeBytes(data.getBytes());
         ByteBuf buf2 = buf.duplicate();
         v(buf2);
     }
@@ -50,8 +48,7 @@ public void testDirectP() throws Exception {
         ByteBufAllocator a   = TestAllocUtil.direct();
         ByteBuf          buf = a.allocate(16);
 
-        buf.putBytes(data.getBytes());
-        buf.flip();
+        buf.writeBytes(data.getBytes());
         ByteBuf buf2 = buf.duplicate();
         v(buf2);
     }
@@ -60,8 +57,7 @@ public void testDirectP() throws Exception {
     public void testHeap() {
         ByteBuf buf = ByteBuf.direct(16);
 
-        buf.putBytes(data.getBytes());
-        buf.flip();
+        buf.writeBytes(data.getBytes());
         ByteBuf buf2 = buf.duplicate();
         v(buf2);
     }
@@ -71,8 +67,7 @@ public void testHeapP() throws Exception {
         ByteBufAllocator a   = TestAllocUtil.heap();
         ByteBuf          buf = a.allocate(16);
 
-        buf.putBytes(data.getBytes());
-        buf.flip();
+        buf.writeBytes(data.getBytes());
         ByteBuf buf2 = buf.duplicate();
         v(buf2);
     }
diff --git a/firenio-test/src/main/java/test/io/buffer/TestExpansion.java b/firenio-test/src/main/java/test/io/buffer/TestExpansion.java
index 8d09696f3..2e6ffab17 100644
--- a/firenio-test/src/main/java/test/io/buffer/TestExpansion.java
+++ b/firenio-test/src/main/java/test/io/buffer/TestExpansion.java
@@ -31,8 +31,7 @@ public class TestExpansion {
     static final byte[] data = "aaaa".getBytes();
 
     private static boolean v(ByteBuf buf) {
-        buf.flip();
-        String s = new String(buf.getBytes());
+        String s = new String(buf.readBytes());
         if (s.length() != 50) {
             return false;
         }
@@ -49,8 +48,8 @@ public void arrayPool() throws Exception {
         ByteBufAllocator alloc = TestAllocUtil.heap(1024 * 4);
         ByteBuf          buf   = alloc.allocate(2);
         for (int i = 0; i < 10; i++) {
-            buf.putBytes(data);
-            buf.putByte(a);
+            buf.writeBytes(data);
+            buf.writeByte(a);
             alloc.allocate(1);
         }
         Assert.assertTrue(v(buf));
@@ -60,8 +59,8 @@ public void arrayPool() throws Exception {
     public void arrayUnPool() {
         ByteBuf buf = ByteBuf.heap(2);
         for (int i = 0; i < 10; i++) {
-            buf.putBytes(data);
-            buf.putByte(a);
+            buf.writeBytes(data);
+            buf.writeByte(a);
         }
         Assert.assertTrue(v(buf));
     }
@@ -71,8 +70,8 @@ public void directPool() throws Exception {
         ByteBufAllocator alloc = TestAllocUtil.direct(1024 * 4);
         ByteBuf          buf   = alloc.allocate(2);
         for (int i = 0; i < 10; i++) {
-            buf.putBytes(data);
-            buf.putByte(a);
+            buf.writeBytes(data);
+            buf.writeByte(a);
             alloc.allocate(1);
         }
         Assert.assertTrue(v(buf));
@@ -82,8 +81,8 @@ public void directPool() throws Exception {
     public void directUnPool() {
         ByteBuf buf = ByteBuf.direct(2);
         for (int i = 0; i < 10; i++) {
-            buf.putBytes(data);
-            buf.putByte(a);
+            buf.writeBytes(data);
+            buf.writeByte(a);
         }
         Assert.assertTrue(v(buf));
     }
diff --git a/firenio-test/src/main/java/test/io/buffer/TestPooledBytebuf.java b/firenio-test/src/main/java/test/io/buffer/TestPooledBytebuf.java
index 74e08e87b..f6a36d9df 100644
--- a/firenio-test/src/main/java/test/io/buffer/TestPooledBytebuf.java
+++ b/firenio-test/src/main/java/test/io/buffer/TestPooledBytebuf.java
@@ -50,10 +50,10 @@ public void testAlloc() throws Exception {
                     ByteBuf buf = a.allocate(pa);
                     a.toString();
                     bufs.add(buf);
-                    alloc += buf.limit();
-                    if (buf.limit() % 3 != 0) {
+                    alloc += buf.writeIndex();
+                    if (buf.writeIndex() % 3 != 0) {
                         buf.release();
-                        alloc -= buf.limit();
+                        alloc -= buf.writeIndex();
                         bufs.remove(buf);
                     }
                 }
diff --git a/firenio-test/src/main/java/test/io/http11/TestSimpleHttpClient.java b/firenio-test/src/main/java/test/io/http11/TestSimpleHttpClient.java
index 3befc45cd..a80d5c3e3 100644
--- a/firenio-test/src/main/java/test/io/http11/TestSimpleHttpClient.java
+++ b/firenio-test/src/main/java/test/io/http11/TestSimpleHttpClient.java
@@ -58,7 +58,7 @@ public void accept(Channel ch, Frame frame) {
         context.addChannelEventListener(new LoggerChannelOpenListener());
         context.setSslContext(sslContext);
         long    start = Util.now();
-        Channel ch    = context.connect();
+        Channel ch    = context.connect(9999999);
         ch.writeAndFlush(new ClientHttpFrame("/test?p=2222"));
         w.await(3000);
         System.out.println(Util.past(start));
diff --git a/firenio-test/src/main/java/test/io/http11/TestSimpleHttpClient2.java b/firenio-test/src/main/java/test/io/http11/TestSimpleHttpClient2.java
index 9657ca2c0..097193f33 100644
--- a/firenio-test/src/main/java/test/io/http11/TestSimpleHttpClient2.java
+++ b/firenio-test/src/main/java/test/io/http11/TestSimpleHttpClient2.java
@@ -77,7 +77,7 @@ public void channelOpened(Channel ch) throws Exception {
         Channel         ch = context.connect(999999);
         ClientHttpFrame f  = new ClientHttpFrame(url, HttpMethod.GET);
         //        f.setRequestHeader(HttpHeader.Host, host);
-        //        f.setContent("abc123".getBytes());
+        //        f.setContent("abc123".readBytes());
         ch.write(f);
         ch.writeAndFlush(f);
 
diff --git a/firenio-test/src/main/java/test/io/http11/TestSimpleWebSocketClient.java b/firenio-test/src/main/java/test/io/http11/TestSimpleWebSocketClient.java
index 6ee9f86e6..3b29a258b 100644
--- a/firenio-test/src/main/java/test/io/http11/TestSimpleWebSocketClient.java
+++ b/firenio-test/src/main/java/test/io/http11/TestSimpleWebSocketClient.java
@@ -18,6 +18,8 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import test.test.TestUtil;
+
 import com.alibaba.fastjson.JSON;
 import com.firenio.codec.http11.ClientHttpCodec;
 import com.firenio.codec.http11.ClientHttpFrame;
@@ -61,7 +63,7 @@ public void accept(Channel ch, Frame frame) throws Exception {
             }
         };
 
-        String            host = "www.firenio.com";
+        String            host = "firenio.com";
         int               port = 443;
         NioEventLoopGroup g    = new NioEventLoopGroup();
         g.setEnableMemoryPool(false);
@@ -82,6 +84,13 @@ public void accept(Channel ch, Frame frame) throws Exception {
         frame.setRequestHeader(HttpHeader.Accept_Encoding, "gzip, deflate, sdch");
         frame.setRequestHeader(HttpHeader.Accept_Language, "zh-CN,zh;q=0.8");
         ch.writeAndFlush(frame);
+        Util.sleep(100);
+        WebSocketFrame      f2  = new WebSocketFrame();
+        Map map = new HashMap<>();
+        map.put("action", "new-message");
+        map.put("message", TestUtil.newString(1024 * 8));
+        f2.setString(JSON.toJSONString(map), ch);
+        ch.writeAndFlush(f2);
         Util.sleep(999999999);
         Util.close(context);
 
diff --git a/firenio-core/src/main/java/com/firenio/collection/Attributes.java b/firenio-test/src/main/java/test/io/jni/TestJNA.java
similarity index 64%
rename from firenio-core/src/main/java/com/firenio/collection/Attributes.java
rename to firenio-test/src/main/java/test/io/jni/TestJNA.java
index 2e8d41e5d..cbc73192a 100644
--- a/firenio-core/src/main/java/com/firenio/collection/Attributes.java
+++ b/firenio-test/src/main/java/test/io/jni/TestJNA.java
@@ -13,23 +13,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.firenio.collection;
+package test.io.jni;
 
-import java.util.Map;
-import java.util.Set;
+/**
+ * @author: wangkai
+ **/
+public class TestJNA {
 
-public interface Attributes {
 
-    Map attributes();
+    public static void main(String[] args) {
 
-    void clearAttributes();
 
-    Object getAttribute(Object key);
 
-    Set getAttributeNames();
 
-    Object removeAttribute(Object key);
 
-    void setAttribute(Object key, Object value);
+    }
+
 
 }
diff --git a/firenio-test/src/main/java/test/io/lenthvalue/TestByteBufPool.java b/firenio-test/src/main/java/test/io/lenthvalue/TestByteBufPool.java
new file mode 100644
index 000000000..bfb47e44b
--- /dev/null
+++ b/firenio-test/src/main/java/test/io/lenthvalue/TestByteBufPool.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.io.lenthvalue;
+
+import com.firenio.buffer.ByteBuf;
+import com.firenio.codec.lengthvalue.LengthValueCodec;
+import com.firenio.codec.lengthvalue.LengthValueFrame;
+import com.firenio.component.Channel;
+import com.firenio.component.ChannelConnector;
+import com.firenio.component.Frame;
+import com.firenio.component.IoEventHandle;
+import com.firenio.component.LoggerChannelOpenListener;
+
+/**
+ * @author: wangkai
+ **/
+public class TestByteBufPool {
+
+    public static void main(String[] args) throws Exception {
+
+        ChannelConnector context = new ChannelConnector("192.168.1.102", 6500);
+        context.addChannelEventListener(new LoggerChannelOpenListener());
+        context.addProtocolCodec(new LengthValueCodec());
+        Channel ch  = context.connect(3000);
+        ByteBuf buf = ch.allocate();
+        ch.close();
+        buf.release();
+
+    }
+
+
+}
diff --git a/firenio-test/src/main/java/test/io/load/http11/TestHttpLoadServerTFB.java b/firenio-test/src/main/java/test/io/load/http11/TestHttpLoadServerTFB.java
index 72d76eea2..fc4847fbb 100644
--- a/firenio-test/src/main/java/test/io/load/http11/TestHttpLoadServerTFB.java
+++ b/firenio-test/src/main/java/test/io/load/http11/TestHttpLoadServerTFB.java
@@ -15,22 +15,23 @@
  */
 package test.io.load.http11;
 
-import java.io.IOException;
-import java.util.Arrays;
-
 import com.firenio.Options;
+import com.firenio.buffer.ByteBuf;
 import com.firenio.codec.http11.HttpCodec;
 import com.firenio.codec.http11.HttpConnection;
 import com.firenio.codec.http11.HttpContentType;
 import com.firenio.codec.http11.HttpDateUtil;
 import com.firenio.codec.http11.HttpFrame;
 import com.firenio.codec.http11.HttpStatus;
+import com.firenio.collection.AttributeKey;
+import com.firenio.collection.AttributeMap;
 import com.firenio.collection.ByteTree;
 import com.firenio.common.Util;
 import com.firenio.component.Channel;
 import com.firenio.component.ChannelAcceptor;
 import com.firenio.component.ChannelEventListener;
 import com.firenio.component.ChannelEventListenerAdapter;
+import com.firenio.component.FastThreadLocal;
 import com.firenio.component.Frame;
 import com.firenio.component.IoEventHandle;
 import com.firenio.component.NioEventLoopGroup;
@@ -40,14 +41,15 @@
 import com.firenio.log.LoggerFactory;
 import com.jsoniter.output.JsonStream;
 import com.jsoniter.output.JsonStreamPool;
-import com.jsoniter.spi.JsonException;
+import com.jsoniter.spi.Slice;
 
 /**
  * @author wangkai
  */
 public class TestHttpLoadServerTFB {
 
-    static final byte[] STATIC_PLAINTEXT = "Hello, World!".getBytes();
+    static final AttributeKey JSON_BUF         = newByteBufKey();
+    static final byte[]                STATIC_PLAINTEXT = "Hello, World!".getBytes();
 
     public static void main(String[] args) throws Exception {
         boolean lite       = Util.getBooleanProperty("lite");
@@ -90,9 +92,23 @@ public void accept(Channel ch, Frame frame) throws Exception {
                     f.setContentType(HttpContentType.text_plain);
                     f.setConnection(HttpConnection.NONE);
                 } else if ("/json".equals(action)) {
-                    f.setContent(serializeMsg(new Message("Hello, World!")));
-                    f.setContentType(HttpContentType.application_json);
-                    f.setConnection(HttpConnection.NONE);
+                    ByteBuf    temp   = FastThreadLocal.get().getAttributeUnsafe(JSON_BUF);
+                    JsonStream stream = JsonStreamPool.borrowJsonStream();
+                    try {
+                        stream.reset(null);
+                        stream.writeVal(Message.class, new Message("Hello, World!"));
+                        Slice slice = stream.buffer();
+                        temp.reset(slice.data(), slice.head(), slice.tail());
+                        f.setContent(temp);
+                        f.setContentType(HttpContentType.application_json);
+                        f.setConnection(HttpConnection.NONE);
+                        f.setDate(HttpDateUtil.getDateLine());
+                        ch.writeAndFlush(f);
+                        ch.release(f);
+                    } finally {
+                        JsonStreamPool.returnJsonStream(stream);
+                    }
+                    return;
                 } else {
                     System.err.println("404");
                     f.setString("404,page not found!", ch);
@@ -146,7 +162,6 @@ public void channelClosed(Channel ch) {
             @Override
             public void channelOpened(Channel ch) throws Exception {
                 ch.setOption(SocketOptions.TCP_NODELAY, 1);
-                ch.setOption(SocketOptions.TCP_QUICKACK, 1);
                 ch.setOption(SocketOptions.SO_KEEPALIVE, 0);
             }
         });
@@ -154,17 +169,8 @@ public void channelOpened(Channel ch) throws Exception {
         context.bind();
     }
 
-    private static byte[] serializeMsg(Message obj) {
-        JsonStream stream = JsonStreamPool.borrowJsonStream();
-        try {
-            stream.reset(null);
-            stream.writeVal(Message.class, obj);
-            return Arrays.copyOfRange(stream.buffer().data(), 0, stream.buffer().tail());
-        } catch (IOException e) {
-            throw new JsonException(e);
-        } finally {
-            JsonStreamPool.returnJsonStream(stream);
-        }
+    static AttributeKey newByteBufKey() {
+        return FastThreadLocal.valueOfKey("JSON_BUF", (AttributeMap map, int key) -> map.setAttribute(key, ByteBuf.heap(0)));
     }
 
     static class Message {
diff --git a/firenio-test/src/main/java/test/io/load/http11/TestLoadClient.java b/firenio-test/src/main/java/test/io/load/http11/TestLoadClient.java
index ce84734cd..5038c4b2d 100644
--- a/firenio-test/src/main/java/test/io/load/http11/TestLoadClient.java
+++ b/firenio-test/src/main/java/test/io/load/http11/TestLoadClient.java
@@ -16,6 +16,7 @@
 package test.io.load.http11;
 
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import com.firenio.buffer.ByteBuf;
 import com.firenio.codec.http11.ClientHttpCodec;
@@ -38,72 +39,82 @@ public static void main(String[] args) throws Exception {
 
         String request = "GET /plaintext HTTP/1.1\r\n" + "Host: localhost:8080\r\n" + "Connection: keep-alive\r\n" + "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36\r\n" + "Accept: text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7\r\n\r\n";
 
-        request = "GET /plaintext HTTP/1.1\r\n" + "Host: localhost:8080\r\n" + "Connection: keep-alive\r\n" + "User-Agent: ApacheBench/2.3\r\n" + "Accept: */*\r\n\r\n";
-        final String  host = "127.0.0.1";
-        final int     port = 8080;
-        final int     rpc  = 1024 * 4 * 16;
-        final int     ts   = 2;
-        final int     cpt  = 32;
-        final int     pipe = 64;
-        final ByteBuf req  = buildReqest(request, pipe);
+        //        request = "GET /plaintext HTTP/1.1\r\n" + "Host: localhost:8080\r\n" + "Connection: keep-alive\r\n" + "User-Agent: ApacheBench/2.3\r\n" + "Accept: */*\r\n\r\n";
 
-        test(host, port, req, rpc, ts, cpt, pipe);
+        TestLoadRound round = new TestLoadRound();
+        round.host = "127.0.0.1";
+        round.port = 8080;
+        round.pipes = 16;
+        round.threads = 4;
+        round.requests = 1024 * 1024 * 1;
+        round.connections = 1024 * 8;
+        round.request_buf = buildRequest(request, round.pipes);
+
+        test(round);
 
     }
 
-    private static ByteBuf buildReqest(String request, int pipe) {
+    private static ByteBuf buildRequest(String request, int pipes) {
         byte[]  bytes = request.getBytes();
-        ByteBuf buf   = ByteBuf.direct(bytes.length * pipe);
-        for (int i = 0; i < pipe; i++) {
-            buf.putBytes(bytes);
+        ByteBuf buf   = ByteBuf.direct(bytes.length * pipes);
+        for (int i = 0; i < pipes; i++) {
+            buf.writeBytes(bytes);
         }
-        return buf.flip();
+        return buf;
     }
 
-    public static void test(final String host, final int port, final ByteBuf req, final int rpc, final int ts, final int cpt, final int pipe) throws Exception {
-        final int cs    = cpt * ts;
-        final int count = rpc * cs;
-        final int batch = count / pipe;
-        DebugUtil.info("ts:" + ts);
-        DebugUtil.info("cs:" + cs);
-        DebugUtil.info("count:" + count);
-        DebugUtil.info("pipe:" + pipe);
+    public static void test(TestLoadRound round) throws Exception {
+        final String  host        = round.host;
+        final ByteBuf buf         = round.request_buf;
+        final int     port        = round.port;
+        final int     pipes       = round.pipes;
+        final int     threads     = round.threads;
+        final int     requests    = round.requests;
+        final int     connections = round.connections;
+        final int     batch       = requests / pipes;
+        DebugUtil.info("requests:" + requests);
+        DebugUtil.info("threads:" + threads);
+        DebugUtil.info("connections:" + connections);
+        DebugUtil.info("pipes:" + pipes);
         DebugUtil.info("batch:" + batch);
-        NioEventLoopGroup g = new NioEventLoopGroup(true, ts, Integer.MAX_VALUE);
+        NioEventLoopGroup g = new NioEventLoopGroup(true, threads, Integer.MAX_VALUE);
         g.start();
-        Channel[] chs = new Channel[cs];
+        Channel[] chs = new Channel[connections];
         DebugUtil.info("build connections...");
-        long           last    = Util.now();
-        CountDownLatch c_latch = new CountDownLatch(cs);
-        CountDownLatch b_latch = new CountDownLatch(batch);
-        for (int i = 0; i < cs; i++) {
+        CountDownLatch c_latch    = new CountDownLatch(connections);
+        CountDownLatch b_latch    = new CountDownLatch(batch);
+        AtomicInteger  c_complete = new AtomicInteger();
+        long           last       = Util.now();
+        for (int i = 0; i < connections; i++) {
             ChannelConnector context = new ChannelConnector(g.getNext(), host, port);
             context.setPrintConfig(false);
             context.addProtocolCodec(new ClientHttpCodec());
             context.setIoEventHandle(new IoEventHandle() {
 
                 int c = 0;
-                int b = batch / cs;
+                int b = batch / connections;
 
                 @Override
-                public void accept(Channel ch, Frame frame) throws Exception {
-                    if (++c == pipe) {
+                public void accept(Channel ch, Frame frame) {
+                    if (++c == pipes) {
                         c = 0;
                         b_latch.countDown();
-                        if (--b == 0) {
-                            //                            DebugUtil.info("c complate......");
+                        if (--b > 0) {
+                            ch.writeAndFlush(buf.duplicate());
                         } else {
-                            ch.writeAndFlush(req.duplicate());
+                            DebugUtil.info("c complate......" + c_complete.incrementAndGet());
                         }
                     }
                 }
             });
-            final int ii = i;
-            //            context.addChannelEventListener(new LoggerChannelOpenListener());
+            final int i_copy = i;
             context.connect((ch, ex) -> {
-                chs[ii] = ch;
+                if (ex != null) {
+                    ex.printStackTrace();
+                }
+                chs[i_copy] = ch;
                 c_latch.countDown();
-            });
+            }, 9000);
         }
         c_latch.await();
         DebugUtil.info("build connections cost:" + (Util.now() - last));
@@ -111,16 +122,28 @@ public void accept(Channel ch, Frame frame) throws Exception {
         DebugUtil.info("start request...");
         last = Util.now();
         for (int i = 0; i < chs.length; i++) {
-            chs[i].writeAndFlush(req.duplicate());
+            chs[i].writeAndFlush(buf.duplicate());
         }
         b_latch.await();
         long cost = (Util.now() - last);
         DebugUtil.info("request cost:" + cost);
-        DebugUtil.info("request rps:" + (count * 1000d / cost));
+        DebugUtil.info("request rps:" + (requests * 1000d / cost));
         for (int i = 0; i < chs.length; i++) {
             chs[i].close();
         }
         g.stop();
     }
 
+    static class TestLoadRound {
+
+        String  host;
+        ByteBuf request_buf;
+        int     port;
+        int     threads;
+        int     pipes;
+        int     requests;
+        int     connections;
+
+    }
+
 }
diff --git a/firenio-test/src/main/java/test/io/udp/TestUDPClient.java b/firenio-test/src/main/java/test/io/udp/TestUDPClient.java
index e6a03ebc1..74baac58f 100644
--- a/firenio-test/src/main/java/test/io/udp/TestUDPClient.java
+++ b/firenio-test/src/main/java/test/io/udp/TestUDPClient.java
@@ -37,7 +37,7 @@ public static void main(String[] args) throws Exception {
         //
         //        DatagramChannel ch = connector.connect();
         //
-        //        DatagramPacket packet = DatagramPacket.createSendPacket("hello world!".getBytes());
+        //        DatagramPacket packet = DatagramPacket.createSendPacket("hello world!".readBytes());
         //
         //        ch.sendPacket(packet);
         //
diff --git a/firenio-test/src/main/java/test/io/udp/TestUDPReceiveHandle.java b/firenio-test/src/main/java/test/io/udp/TestUDPReceiveHandle.java
index 32c14eccf..374099102 100644
--- a/firenio-test/src/main/java/test/io/udp/TestUDPReceiveHandle.java
+++ b/firenio-test/src/main/java/test/io/udp/TestUDPReceiveHandle.java
@@ -66,7 +66,7 @@ public class TestUDPReceiveHandle {
     //
     //        for (int i = 0; i < 10000000; i++) {
     //
-    //            byte[] data = (inviteUsername + i).getBytes();
+    //            byte[] data = (inviteUsername + i).readBytes();
     //
     //            DatagramPacket packet = factory.createDatagramPacket(data);
     //
@@ -103,7 +103,7 @@ public class TestUDPReceiveHandle {
     //
     //        for (int i = 0; i < 10000000; i++) {
     //
-    //            byte[] data = (client.getInviteUsername() + i).getBytes();
+    //            byte[] data = (client.getInviteUsername() + i).readBytes();
     //
     //            DatagramPacket packet = factory.createDatagramPacket(data);
     //
diff --git a/firenio-test/src/main/java/test/io/udp/TestUDPServer.java b/firenio-test/src/main/java/test/io/udp/TestUDPServer.java
index 1465cc8c1..ddfeb4491 100644
--- a/firenio-test/src/main/java/test/io/udp/TestUDPServer.java
+++ b/firenio-test/src/main/java/test/io/udp/TestUDPServer.java
@@ -29,7 +29,7 @@ public static void main(String[] args) throws IOException {
         //
         //                DebugUtil.debug(req);
         //
-        //                byte[] resMsg = ("yes ," + req).getBytes(Encoding.UTF8);
+        //                byte[] resMsg = ("yes ," + req).readBytes(Encoding.UTF8);
         //
         //                DatagramPacket res = DatagramPacket.createSendPacket(resMsg);
         //
diff --git a/firenio-test/src/main/java/test/others/FibonacciSeq.java b/firenio-test/src/main/java/test/others/FibonacciSeq.java
index 95f23611a..b41cacfd7 100644
--- a/firenio-test/src/main/java/test/others/FibonacciSeq.java
+++ b/firenio-test/src/main/java/test/others/FibonacciSeq.java
@@ -31,7 +31,7 @@ static long fi(long n) {
         long n_2 = 0;
         long n_1 = 1;
         long sum = n_2 + n_1;
-        for (int i = 1; i < n; i++) {
+        for (; n > 0; n--) {
             n_2 = n_1;
             n_1 = sum;
             sum = n_2 + n_1;
diff --git a/firenio-test/src/main/java/test/others/GraphicsTest.java b/firenio-test/src/main/java/test/others/GraphicsTest.java
index 44a919bec..cb9616b37 100644
--- a/firenio-test/src/main/java/test/others/GraphicsTest.java
+++ b/firenio-test/src/main/java/test/others/GraphicsTest.java
@@ -279,14 +279,14 @@ void drawTest(Graphics gra) {
                 boolean[] tar = bits[i];
                 for (int j = 0; j < width; j++) {
                     byte b = array[bIndex++];
-                    tar[j * cheng + 0] = ByteUtil.getBoolean(b, 0);
-                    tar[j * cheng + 1] = ByteUtil.getBoolean(b, 1);
-                    tar[j * cheng + 2] = ByteUtil.getBoolean(b, 2);
-                    tar[j * cheng + 3] = ByteUtil.getBoolean(b, 3);
-                    tar[j * cheng + 4] = ByteUtil.getBoolean(b, 4);
-                    tar[j * cheng + 5] = ByteUtil.getBoolean(b, 5);
-                    tar[j * cheng + 6] = ByteUtil.getBoolean(b, 6);
-                    tar[j * cheng + 7] = ByteUtil.getBoolean(b, 7);
+                    tar[j * cheng + 0] = ByteUtil.getBit(b, 0);
+                    tar[j * cheng + 1] = ByteUtil.getBit(b, 1);
+                    tar[j * cheng + 2] = ByteUtil.getBit(b, 2);
+                    tar[j * cheng + 3] = ByteUtil.getBit(b, 3);
+                    tar[j * cheng + 4] = ByteUtil.getBit(b, 4);
+                    tar[j * cheng + 5] = ByteUtil.getBit(b, 5);
+                    tar[j * cheng + 6] = ByteUtil.getBit(b, 6);
+                    tar[j * cheng + 7] = ByteUtil.getBit(b, 7);
 
                     tar[j * cheng + 0] = r.nextBoolean();
                     tar[j * cheng + 1] = r.nextBoolean();
diff --git a/firenio-test/src/main/java/test/others/RBTree.java b/firenio-test/src/main/java/test/others/RBTree.java
new file mode 100644
index 000000000..1060eb98b
--- /dev/null
+++ b/firenio-test/src/main/java/test/others/RBTree.java
@@ -0,0 +1,687 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.others;
+
+/**
+ * @author: wangkai
+ **/
+public class RBTree {
+
+    private RBTNode mRoot;    // 根结点
+
+    private static final boolean RED   = false;
+    private static final boolean BLACK = true;
+
+    public class RBTNode {
+        boolean color;        // 颜色
+        int     key;        // 关键字(键值)
+        V       value;
+        RBTNode left;    // 左孩子
+        RBTNode right;    // 右孩子
+        RBTNode parent;    // 父结点
+
+        public String toString() {
+            return "" + key + (this.color == RED ? "(R)" : "B");
+        }
+    }
+
+    public RBTree() {
+        mRoot = null;
+    }
+
+    private RBTNode parentOf(RBTNode node) {
+        return node != null ? node.parent : null;
+    }
+
+    private boolean colorOf(RBTNode node) {
+        return node != null ? node.color : BLACK;
+    }
+
+    private boolean isRed(RBTNode node) {
+        return ((node != null) && (node.color == RED)) ? true : false;
+    }
+
+    private boolean isBlack(RBTNode node) {
+        return !isRed(node);
+    }
+
+    private void setBlack(RBTNode node) {
+        if (node != null)
+            node.color = BLACK;
+    }
+
+    private void setRed(RBTNode node) {
+        if (node != null)
+            node.color = RED;
+    }
+
+    private void setParent(RBTNode node, RBTNode parent) {
+        if (node != null)
+            node.parent = parent;
+    }
+
+    private void setColor(RBTNode node, boolean color) {
+        if (node != null)
+            node.color = color;
+    }
+
+    /*
+     * 前序遍历"红黑树"
+     */
+    private void preOrder(RBTNode tree) {
+        if (tree != null) {
+            System.out.print(tree.key + " ");
+            preOrder(tree.left);
+            preOrder(tree.right);
+        }
+    }
+
+    public void preOrder() {
+        preOrder(mRoot);
+    }
+
+    /*
+     * 中序遍历"红黑树"
+     */
+    private void inOrder(RBTNode tree) {
+        if (tree != null) {
+            inOrder(tree.left);
+            System.out.print(tree.key + " ");
+            inOrder(tree.right);
+        }
+    }
+
+    public void inOrder() {
+        inOrder(mRoot);
+    }
+
+    /*
+     * 后序遍历"红黑树"
+     */
+    private void postOrder(RBTNode tree) {
+        if (tree != null) {
+            postOrder(tree.left);
+            postOrder(tree.right);
+            System.out.print(tree.key + " ");
+        }
+    }
+
+    public void postOrder() {
+        postOrder(mRoot);
+    }
+
+    /*
+     * (递归实现)查找"红黑树x"中键值为key的节点
+     */
+    private RBTNode search(RBTNode x, int key) {
+        if (x == null)
+            return x;
+
+        int cmp = key - x.key;//TODO
+        if (cmp < 0)
+            return search(x.left, key);
+        else if (cmp > 0)
+            return search(x.right, key);
+        else
+            return x;
+    }
+
+    public RBTNode search(int key) {
+        return search(mRoot, key);
+    }
+
+    /*
+     * (非递归实现)查找"红黑树x"中键值为key的节点
+     */
+    private RBTNode iterativeSearch(RBTNode x, int key) {
+        while (x != null) {
+            int cmp = key - x.key;//TODO
+
+            if (cmp < 0)
+                x = x.left;
+            else if (cmp > 0)
+                x = x.right;
+            else
+                return x;
+        }
+
+        return x;
+    }
+
+    public RBTNode iterativeSearch(int key) {
+        return iterativeSearch(mRoot, key);
+    }
+
+    /*
+     * 查找最小结点:返回tree为根结点的红黑树的最小结点。
+     */
+    private RBTNode minimum(RBTNode tree) {
+        if (tree == null)
+            return null;
+
+        while (tree.left != null)
+            tree = tree.left;
+        return tree;
+    }
+
+    public RBTNode minimum() {
+        return minimum(mRoot);
+    }
+
+    /*
+     * 查找最大结点:返回tree为根结点的红黑树的最大结点。
+     */
+    private RBTNode maximum(RBTNode tree) {
+        if (tree == null)
+            return null;
+
+        while (tree.right != null)
+            tree = tree.right;
+        return tree;
+    }
+
+    public RBTNode maximum() {
+        return maximum(mRoot);
+    }
+
+    /*
+     * 找结点(x)的后继结点。即,查找"红黑树中数据值大于该结点"的"最小结点"。
+     */
+    public RBTNode successor(RBTNode x) {
+        // 如果x存在右孩子,则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。
+        if (x.right != null)
+            return minimum(x.right);
+
+        // 如果x没有右孩子。则x有以下两种可能:
+        // (01) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。
+        // (02) x是"一个右孩子",则查找"x的最低的父结点,并且该父结点要具有左孩子",找到的这个"最低的父结点"就是"x的后继结点"。
+        RBTNode y = x.parent;
+        while ((y != null) && (x == y.right)) {
+            x = y;
+            y = y.parent;
+        }
+
+        return y;
+    }
+
+    /*
+     * 找结点(x)的前驱结点。即,查找"红黑树中数据值小于该结点"的"最大结点"。
+     */
+    public RBTNode predecessor(RBTNode x) {
+        // 如果x存在左孩子,则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。
+        if (x.left != null)
+            return maximum(x.left);
+
+        // 如果x没有左孩子。则x有以下两种可能:
+        // (01) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。
+        // (01) x是"一个左孩子",则查找"x的最低的父结点,并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"。
+        RBTNode y = x.parent;
+        while ((y != null) && (x == y.left)) {
+            x = y;
+            y = y.parent;
+        }
+
+        return y;
+    }
+
+    /*
+     * 对红黑树的节点(x)进行左旋转
+     *
+     * 左旋示意图(对节点x进行左旋):
+     *      px                              px
+     *     /                               /
+     *    x                               y
+     *   /  \      --(左旋)-.           / \                #
+     *  lx   y                          x  ry
+     *     /   \                       /  \
+     *    ly   ry                     lx  ly
+     *
+     *
+     */
+    private void leftRotate(RBTNode x) {
+        // 设置x的右孩子为y
+        RBTNode y = x.right;
+
+        // 将 “y的左孩子” 设为 “x的右孩子”;
+        // 如果y的左孩子非空,将 “x” 设为 “y的左孩子的父亲”
+        x.right = y.left;
+        if (y.left != null)
+            y.left.parent = x;
+
+        // 将 “x的父亲” 设为 “y的父亲”
+        y.parent = x.parent;
+
+        if (x.parent == null) {
+            this.mRoot = y;            // 如果 “x的父亲” 是空节点,则将y设为根节点
+        } else {
+            if (x.parent.left == x)
+                x.parent.left = y;    // 如果 x是它父节点的左孩子,则将y设为“x的父节点的左孩子”
+            else
+                x.parent.right = y;    // 如果 x是它父节点的左孩子,则将y设为“x的父节点的左孩子”
+        }
+
+        // 将 “x” 设为 “y的左孩子”
+        y.left = x;
+        // 将 “x的父节点” 设为 “y”
+        x.parent = y;
+    }
+
+    /*
+     * 对红黑树的节点(y)进行右旋转
+     *
+     * 右旋示意图(对节点y进行左旋):
+     *            py                               py
+     *           /                                /
+     *          y                                x
+     *         /  \      --(右旋)-.            /  \                     #
+     *        x   ry                           lx   y
+     *       / \                                   / \                   #
+     *      lx  rx                                rx  ry
+     *
+     */
+    private void rightRotate(RBTNode y) {
+        // 设置x是当前节点的左孩子。
+        RBTNode x = y.left;
+
+        // 将 “x的右孩子” 设为 “y的左孩子”;
+        // 如果"x的右孩子"不为空的话,将 “y” 设为 “x的右孩子的父亲”
+        y.left = x.right;
+        if (x.right != null)
+            x.right.parent = y;
+
+        // 将 “y的父亲” 设为 “x的父亲”
+        x.parent = y.parent;
+
+        if (y.parent == null) {
+            this.mRoot = x;            // 如果 “y的父亲” 是空节点,则将x设为根节点
+        } else {
+            if (y == y.parent.right)
+                y.parent.right = x;    // 如果 y是它父节点的右孩子,则将x设为“y的父节点的右孩子”
+            else
+                y.parent.left = x;    // (y是它父节点的左孩子) 将x设为“x的父节点的左孩子”
+        }
+
+        // 将 “y” 设为 “x的右孩子”
+        x.right = y;
+
+        // 将 “y的父节点” 设为 “x”
+        y.parent = x;
+    }
+
+    /*
+     * 红黑树插入修正函数
+     *
+     * 在向红黑树中插入节点之后(失去平衡),再调用该函数;
+     * 目的是将它重新塑造成一颗红黑树。
+     *
+     * 参数说明:
+     *     node 插入的结点        // 对应《算法导论》中的z
+     */
+    private void insertFixUp(RBTNode node) {
+        RBTNode parent, gparent;
+
+        // 若“父节点存在,并且父节点的颜色是红色”
+        while (((parent = parentOf(node)) != null) && isRed(parent)) {
+            gparent = parentOf(parent);
+
+            //若“父节点”是“祖父节点的左孩子”
+            if (parent == gparent.left) {
+                // Case 1条件:叔叔节点是红色
+                RBTNode uncle = gparent.right;
+                if ((uncle != null) && isRed(uncle)) {
+                    setBlack(uncle);
+                    setBlack(parent);
+                    setRed(gparent);
+                    node = gparent;
+                    continue;
+                }
+
+                // Case 2条件:叔叔是黑色,且当前节点是右孩子
+                if (parent.right == node) {
+                    RBTNode tmp;
+                    leftRotate(parent);
+                    tmp = parent;
+                    parent = node;
+                    node = tmp;
+                }
+
+                // Case 3条件:叔叔是黑色,且当前节点是左孩子。
+                setBlack(parent);
+                setRed(gparent);
+                rightRotate(gparent);
+            } else {    //若“z的父节点”是“z的祖父节点的右孩子”
+                // Case 1条件:叔叔节点是红色
+                RBTNode uncle = gparent.left;
+                if ((uncle != null) && isRed(uncle)) {
+                    setBlack(uncle);
+                    setBlack(parent);
+                    setRed(gparent);
+                    node = gparent;
+                    continue;
+                }
+
+                // Case 2条件:叔叔是黑色,且当前节点是左孩子
+                if (parent.left == node) {
+                    RBTNode tmp;
+                    rightRotate(parent);
+                    tmp = parent;
+                    parent = node;
+                    node = tmp;
+                }
+
+                // Case 3条件:叔叔是黑色,且当前节点是右孩子。
+                setBlack(parent);
+                setRed(gparent);
+                leftRotate(gparent);
+            }
+        }
+
+        // 将根节点设为黑色
+        setBlack(this.mRoot);
+    }
+
+    /*
+     * 将结点插入到红黑树中
+     *
+     * 参数说明:
+     *     node 插入的结点        // 对应《算法导论》中的node
+     */
+    public void insert(RBTNode node) {
+        int     cmp;
+        RBTNode y = null;
+        RBTNode x = this.mRoot;
+
+        // 1. 将红黑树当作一颗二叉查找树,将节点添加到二叉查找树中。
+        while (x != null) {
+            y = x;
+            cmp = node.key - x.key; //TODO
+            if (cmp < 0)
+                x = x.left;
+            else
+                x = x.right;
+        }
+
+        node.parent = y;
+        if (y != null) {
+            cmp = node.key - y.key; //TODO
+            if (cmp < 0)
+                y.left = node;
+            else
+                y.right = node;
+        } else {
+            this.mRoot = node;
+        }
+
+        // 2. 设置节点的颜色为红色
+        node.color = RED;
+
+        // 3. 将它重新修正为一颗二叉查找树
+        insertFixUp(node);
+    }
+
+    /*
+     * 新建结点(key),并将其插入到红黑树中
+     *
+     * 参数说明:
+     *     key 插入结点的键值
+     */
+    public void insert(int key, V value) {
+        RBTNode node = new RBTNode();
+        node.color = BLACK;
+        node.key = key;
+        node.value = value;
+        insert(node);
+    }
+
+    /*
+     * 红黑树删除修正函数
+     *
+     * 在从红黑树中删除插入节点之后(红黑树失去平衡),再调用该函数;
+     * 目的是将它重新塑造成一颗红黑树。
+     *
+     * 参数说明:
+     *     node 待修正的节点
+     */
+    private void removeFixUp(RBTNode node, RBTNode parent) {
+        RBTNode other;
+
+        while ((node == null || isBlack(node)) && (node != this.mRoot)) {
+            if (parent.left == node) {
+                other = parent.right;
+                if (isRed(other)) {
+                    // Case 1: x的兄弟w是红色的
+                    setBlack(other);
+                    setRed(parent);
+                    leftRotate(parent);
+                    other = parent.right;
+                }
+
+                if ((other.left == null || isBlack(other.left)) && (other.right == null || isBlack(other.right))) {
+                    // Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的
+                    setRed(other);
+                    node = parent;
+                    parent = parentOf(node);
+                } else {
+
+                    if (other.right == null || isBlack(other.right)) {
+                        // Case 3: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。
+                        setBlack(other.left);
+                        setRed(other);
+                        rightRotate(other);
+                        other = parent.right;
+                    }
+                    // Case 4: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
+                    setColor(other, colorOf(parent));
+                    setBlack(parent);
+                    setBlack(other.right);
+                    leftRotate(parent);
+                    node = this.mRoot;
+                    break;
+                }
+            } else {
+
+                other = parent.left;
+                if (isRed(other)) {
+                    // Case 1: x的兄弟w是红色的
+                    setBlack(other);
+                    setRed(parent);
+                    rightRotate(parent);
+                    other = parent.left;
+                }
+
+                if ((other.left == null || isBlack(other.left)) && (other.right == null || isBlack(other.right))) {
+                    // Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的
+                    setRed(other);
+                    node = parent;
+                    parent = parentOf(node);
+                } else {
+
+                    if (other.left == null || isBlack(other.left)) {
+                        // Case 3: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。
+                        setBlack(other.right);
+                        setRed(other);
+                        leftRotate(other);
+                        other = parent.left;
+                    }
+
+                    // Case 4: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
+                    setColor(other, colorOf(parent));
+                    setBlack(parent);
+                    setBlack(other.left);
+                    rightRotate(parent);
+                    node = this.mRoot;
+                    break;
+                }
+            }
+        }
+
+        if (node != null)
+            setBlack(node);
+    }
+
+    /*
+     * 删除结点(node),并返回被删除的结点
+     *
+     * 参数说明:
+     *     node 删除的结点
+     */
+    public void remove(RBTNode node) {
+        RBTNode child, parent;
+        boolean color;
+
+        // 被删除节点的"左右孩子都不为空"的情况。
+        if ((node.left != null) && (node.right != null)) {
+            // 被删节点的后继节点。(称为"取代节点")
+            // 用它来取代"被删节点"的位置,然后再将"被删节点"去掉。
+            RBTNode replace = node;
+
+            // 获取后继节点
+            replace = replace.right;
+            while (replace.left != null)
+                replace = replace.left;
+
+            // "node节点"不是根节点(只有根节点不存在父节点)
+            if (parentOf(node) != null) {
+                if (parentOf(node).left == node)
+                    parentOf(node).left = replace;
+                else
+                    parentOf(node).right = replace;
+            } else {
+                // "node节点"是根节点,更新根节点。
+                this.mRoot = replace;
+            }
+
+            // child是"取代节点"的右孩子,也是需要"调整的节点"。
+            // "取代节点"肯定不存在左孩子!因为它是一个后继节点。
+            child = replace.right;
+            parent = parentOf(replace);
+            // 保存"取代节点"的颜色
+            color = colorOf(replace);
+
+            // "被删除节点"是"它的后继节点的父节点"
+            if (parent == node) {
+                parent = replace;
+            } else {
+                // child不为空
+                if (child != null)
+                    setParent(child, parent);
+                parent.left = child;
+
+                replace.right = node.right;
+                setParent(node.right, replace);
+            }
+
+            replace.parent = node.parent;
+            replace.color = node.color;
+            replace.left = node.left;
+            node.left.parent = replace;
+
+            if (color == BLACK)
+                removeFixUp(child, parent);
+
+            node = null;
+            return;
+        }
+
+        if (node.left != null) {
+            child = node.left;
+        } else {
+            child = node.right;
+        }
+
+        parent = node.parent;
+        // 保存"取代节点"的颜色
+        color = node.color;
+
+        if (child != null)
+            child.parent = parent;
+
+        // "node节点"不是根节点
+        if (parent != null) {
+            if (parent.left == node)
+                parent.left = child;
+            else
+                parent.right = child;
+        } else {
+            this.mRoot = child;
+        }
+
+        if (color == BLACK)
+            removeFixUp(child, parent);
+        node = null;
+    }
+
+    /*
+     * 删除结点(z),并返回被删除的结点
+     *
+     * 参数说明:
+     *     tree 红黑树的根结点
+     *     z 删除的结点
+     */
+    public void remove(int key) {
+        RBTNode node;
+
+        if ((node = search(mRoot, key)) != null)
+            remove(node);
+    }
+
+    /*
+     * 销毁红黑树
+     */
+    private void destroy(RBTNode tree) {
+        if (tree == null)
+            return;
+
+        if (tree.left != null)
+            destroy(tree.left);
+        if (tree.right != null)
+            destroy(tree.right);
+
+        tree = null;
+    }
+
+    public void clear() {
+        destroy(mRoot);
+        mRoot = null;
+    }
+
+    /*
+     * 打印"红黑树"
+     *
+     * key        -- 节点的键值
+     * direction  --  0,表示该节点是根节点;
+     *               -1,表示该节点是它的父结点的左孩子;
+     *                1,表示该节点是它的父结点的右孩子。
+     */
+    private void print(RBTNode tree, int key, int direction) {
+
+        if (tree != null) {
+
+            if (direction == 0)    // tree是根节点
+                System.out.printf("%2d(B) is root\n", tree.key);
+            else                // tree是分支节点
+                System.out.printf("%2d(%s) is %2d's %6s child\n", tree.key, isRed(tree) ? "R" : "B", key, direction == 1 ? "right" : "left");
+
+            print(tree.left, tree.key, -1);
+            print(tree.right, tree.key, 1);
+        }
+    }
+
+    public void print() {
+        if (mRoot != null)
+            print(mRoot, mRoot.key, 0);
+    }
+}
diff --git a/firenio-test/src/main/java/test/others/RBTreeTest.java b/firenio-test/src/main/java/test/others/RBTreeTest.java
new file mode 100644
index 000000000..0359bd55d
--- /dev/null
+++ b/firenio-test/src/main/java/test/others/RBTreeTest.java
@@ -0,0 +1,50 @@
+package test.others;
+
+import org.junit.Test;
+import test.others.RBTree.RBTNode;
+
+import static org.junit.Assert.*;
+
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class RBTreeTest {
+
+  public static void main(String[] args) {
+
+      RBTree tree = new RBTree<>();
+
+      tree.insert(5, "5");
+      tree.insert(2, "2");
+      tree.insert(1, "1");
+      tree.insert(2, "2");
+      tree.insert(4, "4");
+      tree.insert(6, "6");
+
+      for(;;){
+          RBTNode n = tree.maximum();
+          if (n == null){
+              break;
+          }
+          System.out.println(n.value);
+          tree.remove(n);
+      }
+
+
+
+
+  }
+
+}
\ No newline at end of file
diff --git a/firenio-test/src/main/java/test/others/TestBitSet.java b/firenio-test/src/main/java/test/others/TestBitSet.java
new file mode 100644
index 000000000..a79a8c07b
--- /dev/null
+++ b/firenio-test/src/main/java/test/others/TestBitSet.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.others;
+
+import java.util.BitSet;
+
+/**
+ * @author: wangkai
+ **/
+public class TestBitSet {
+
+    public static void main(String[] args) {
+
+        int    cycle     = 256;
+        int    count     = 1024 * 1024;
+        long   startTime = System.currentTimeMillis();
+//        BitSet set       = new BitSet(count);
+        MyBitSet set       = new MyBitSet(count);
+        for (int i = 0; i < cycle; i++) {
+//            testJdkBitSet(set, count);
+                        testMyBitSet(set,count);
+        }
+        long past = System.currentTimeMillis() - startTime;
+
+        System.out.println("cost: " + past);
+
+
+    }
+
+
+    static void testMyBitSet(MyBitSet set, int count) {
+        for (int i = 0; i < count; i++) {
+            set.setFree(i);
+        }
+        for (int i = 0; i < count; i++) {
+            set.clearFree(i);
+        }
+    }
+
+
+    static void testJdkBitSet(BitSet set, int count) {
+        for (int i = 0; i < count; i++) {
+            set.set(i);
+        }
+        for (int i = 0; i < count; i++) {
+            set.clear(i);
+        }
+    }
+
+    static class MyBitSet {
+
+        static final int ADDRESS_BITS_PER_WORD = 6;
+
+        private final long[] frees;
+
+        MyBitSet(int cap) {
+            frees = new long[cap / 8];
+        }
+
+        private static int wordIndex(int bitIndex) {
+            return bitIndex >> ADDRESS_BITS_PER_WORD;
+        }
+
+        private void setFree(int index) {
+            int wordIndex = wordIndex(index);
+            frees[wordIndex] |= (1L << index);
+        }
+
+        private void clearFree(int index) {
+            int wordIndex = wordIndex(index);
+            frees[wordIndex] &= ~(1L << index);
+        }
+
+        private boolean isFree(int index) {
+            int wordIndex = wordIndex(index);
+            return ((frees[wordIndex] & (1L << index)) != 0);
+        }
+
+    }
+
+}
diff --git a/firenio-test/src/main/java/test/others/TestIntMap.java b/firenio-test/src/main/java/test/others/TestIntMap.java
index af406b3cb..1883dfc63 100644
--- a/firenio-test/src/main/java/test/others/TestIntMap.java
+++ b/firenio-test/src/main/java/test/others/TestIntMap.java
@@ -16,7 +16,10 @@
 package test.others;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Random;
 
 import org.junit.Before;
@@ -24,66 +27,105 @@
 
 import com.firenio.collection.IntMap;
 import com.firenio.common.Assert;
+import com.firenio.log.Logger;
+import com.firenio.log.LoggerFactory;
 
 /**
  * @author wangkai
  */
 public class TestIntMap {
 
-    IntMap map  = new IntMap<>(16);
-    List  list = new ArrayList<>(16);
+    static {
+        LoggerFactory.setEnableSLF4JLogger(false);
+    }
+
+    Logger logger = LoggerFactory.getLogger(TestIntMap.class);
+
+    int             cap  = 1000;
+    IntMap map  = new IntMap<>(16);
+    List   list = new ArrayList<>(16);
 
     @Before
     public void before() {
-        Random r = new Random();
-        for (int i = 0; i < 1000; i++) {
-            int    k = r.nextInt(Integer.MAX_VALUE);
-            String v = String.valueOf(k);
-            map.put(k, v);
-            list.add(k);
+        list = newDataList();
+        for (Integer i : list) {
+            map.put(i, i);
+        }
+        logger.info("size: " + list.size());
+        logger.info("list: " + list);
+    }
+
+    List newDataList() {
+        boolean random = true;
+        if (random) {
+            Random        r    = new Random();
+            List list = new ArrayList<>(cap);
+            for (int i = 0; i < cap; i++) {
+                int k = r.nextInt(2000);
+                if (list.contains(k)) {
+                    i--;
+                    continue;
+                }
+                list.add(k);
+            }
+            return list;
+        } else {
+            Integer[]     data = new Integer[]{1817709497, 1020619099, 1759681358, 941541627, 62623315, 508772680, 1298922045, 1361284904, 1807787055, 1736261043, 1533483009, 2069766034, 1175456478, 1493485670, 2145530210, 624325508, 1352607519, 1627640025, 271562923, 277362065, 1285593433, 951112590, 18895618, 327371137, 267540549, 1166392586, 1056315609, 1547479254, 1797755816, 872923760, 1527655293, 1021066745, 1118748990, 954591675, 364696012, 1882523654, 502814131, 411409303, 1630105091, 702509361, 1107872714, 955267293, 272285365, 239231443, 766032801, 1678396841, 1207499992, 1962293781, 1586488331, 128752666, 2035452154, 2067102775, 211036189, 272685222, 1980299665, 927043966, 137601733, 1283953175, 1624734831, 626963384, 1826689683, 332029734, 465608020, 703636845, 124518299, 1519717298, 1996530590, 183665316, 1506942323, 113385373, 411228443, 1075745871, 1440582488, 768784708, 705375231, 692039764, 1330361453, 365909401, 816496113, 66342968, 921874979, 686735326, 296555071, 239347818, 1586967220, 1083835135, 420785459, 1013688874, 1728251336, 1756878477, 655955581, 1791851028, 1737265467, 1175953747, 1644515535, 1336968525, 297897974, 570149783, 2138372232, 1005715272, 1231789306, 449100526, 1415535496, 2025665078, 1053502587, 1916367292, 969079842, 1330621448, 785233193, 1384148040, 1631129903, 1030681122, 88992649, 1395324280, 274707775, 102598045, 1010372994, 157207853, 1426233067, 485466681, 501382132, 2093849149, 22355014, 1337770462, 1895731331, 208093705, 344853362, 754028237, 1406180722, 1898700731, 1206118990, 1561759336, 1982533033, 1288942878, 1131046733, 1322938010, 1696045785, 818876186, 1824800098, 179535844, 1735737270, 101038026, 1344414999, 1285195269, 313773155, 777859132, 29263037, 1880729926, 1446059756, 1879477188, 68071870, 126677599, 2025464300, 59270909, 811447566, 1738431241, 1584517967, 1577522270, 1502717120, 1918770465, 1073919282, 689223796, 446416053, 980978294, 581118695, 1106554817, 77906031, 1368741679, 1497064468, 123287601, 663318531, 1770053852, 1644402683, 1004009525, 1188149805, 889101335, 861631188, 474062207, 890389886, 1269592790, 579319638, 491941208, 1489160880, 1188134225, 1167144532, 796213409, 1260255770, 1877942154, 248536708, 523240804, 1757218366, 1813132670, 1323484764, 484999190, 1399850368, 1490196454, 888943126, 1889642091, 1718975730, 1145693098, 1541060562, 566070742, 80119370, 1152323043, 1128121305, 1163233180, 298984181, 1565716107, 1958338303, 1324983444, 517566020, 1175620548, 859781411, 423787133, 55017669, 1788252097, 1288116689, 1362339068, 1207629485, 1954804565, 226261254, 110828592, 698624880, 2109245206, 1702240787, 469834483, 1413110899, 1986962733, 165470874, 1140715184, 37422297, 558757309, 1446930357, 998681308, 2030691450, 295948270, 1391823671, 781670931, 494748658, 1289511317, 1276834570, 372303567, 1871259605, 1350461314, 360514743, 629839303, 1396000000, 1946017893, 1506561797, 1144687586, 1253353483, 509002845, 1301916600, 1905686998, 1588797914, 1898408735, 1544911738, 1380263778, 1306241875, 110291647, 1876131288, 2106275876, 1952191018, 1060002078, 55371619, 1206461463, 1524457687, 2118154737, 462583799, 1103494573, 1059951529, 1531577193, 96105240, 583155589, 516836596, 1355105156, 2033351800, 1988590538, 367352422, 1139707888, 341539477, 572352295, 1992752504, 1825802903, 1037418879, 1721391466, 480184576, 1467868364, 1707468727, 1057815988, 498927075, 1735322384, 188663603, 358517850, 1893249255, 1483457408, 151211135, 4753500, 258425766, 393144543, 35313149, 1492032128, 1794054814, 319949884, 878511437, 14468106, 726559334, 747382592, 1631978695, 179553049, 1900205563, 202516758, 1781687077, 2085692065, 105568313, 430262263, 1957807934, 106827776, 1314329189, 1019257169, 403824109, 42446911, 2144383463, 310932115, 1656161296, 1490374376, 1952136981, 901239959, 1114525356, 423387263, 462112554, 976126893, 381465390, 1045951134, 363885397, 105832000, 1634283980, 145277872, 1323876078, 1861542952, 473695242, 1620892746, 2065407683, 38903947, 1229648217, 1550918689, 1700203409, 1728252016, 894110682, 728566956, 91586958, 1844901858, 1398945600, 1101007703, 1427318563, 128489405, 1408695251, 130694496, 1372155063, 984749592, 2049132432, 1578446674, 1502320551, 253836111, 1574362990, 1532453404, 66308690, 1444677035, 1031824059, 91015118, 1735867216, 1221268912, 1163911845, 1264062959, 1290890690, 382883076, 1788096469, 1258572669, 299982020, 410837495, 212082742, 2017187970, 1462807551, 298314163, 1272393428, 1617007951, 1049366364, 843627265, 826603487, 810184536, 1549089747, 354745269, 1429811918, 1927377323, 321508193, 1352174264, 1367469216, 1973804814, 1157619224, 745748656, 295167037, 1395823541, 1410302544, 724640078, 242027259, 628590749, 1414188539, 1819479859, 1831553854, 482472584, 2065175, 1447621760, 1198380855, 331159189, 97253692, 1402413561, 1923178957, 1390251643, 1288652373, 159352532, 1197196184, 147478114, 1846411371, 1321394980, 784444937, 2096275038, 1078463133, 455243485, 1536765608, 993327496, 445710124, 1753831299, 814867574, 854336699, 113502387, 1020081780, 297265521, 578764520, 528751731, 1405682126, 34902582, 1180101911, 1130899404, 990931454, 5260736, 1417053179, 914940616, 1629615590, 2145046350, 1150284080, 66968018, 711847850, 198421603, 148553235, 183591044, 23270424, 599914727, 1910646334, 705281950, 144084657, 138656619, 1552145310, 218763282, 1034644568, 693531530, 353940019, 182744379, 1769361046, 1826024555, 2128219492, 1730185262, 144492936, 1752462690, 1990887677, 999548457, 1279030886, 112444086, 437647302, 1947726889, 2057069744, 1558173821, 1447326145, 1950812568, 757871607, 873169316, 6147071, 1618760738, 1841217605, 262927627, 1293317151, 846522024, 1436740394, 821914317, 1970555236, 1814398286, 77310820, 2037154717, 451521906, 1069539503, 1281436970, 1674282060, 1313777317, 328929840, 1910992149, 2051573607, 933465614, 115231602, 482564011, 1577707260, 361128716, 1032440545, 1431181194, 791167101, 846954114, 652822377, 1949752366, 1955697854, 1832648634, 1639720265, 883819359, 962012697, 1808264406, 9627135, 1373187898, 1612699313, 77570286, 2082891107, 2137944793, 1239251, 233292235, 132421072, 885874594, 1286284152, 687118143, 2142735741, 609180969, 161512679, 1433222687, 2017908457, 1517639107, 362188151, 1065668831, 1639978613, 279929256, 1134570610, 944717768, 531838731, 911981251, 688699670, 1335440088, 1071607804, 1927602970, 1887023541, 1334177590, 1360106984, 1513850837, 753621756, 824957520, 260655318, 1340558061, 1910069584, 236442771, 752988516, 87178610, 63454804, 1990804934, 928227096, 1730507896, 1314335879, 1279022340, 1383201236, 97108639, 951636747, 1035298388, 1734252648, 2114338878, 444670848, 2094569446, 855944770, 52882476, 614810639, 1015650541, 2135368256, 2133872426, 1537302403, 121361427, 727990438, 508144624, 1343231377, 522225565, 1295342123, 1616242131, 213478712, 916456733, 931660334, 753657871, 677071683, 419754702, 1924644358, 2078406583, 608931564, 2090076303, 118101879, 338426422, 397678235, 1983406719, 1094460480, 2055428737, 1403719372, 1662264113, 1884271824, 30398171, 1793985806, 1866907532, 1763146777, 187900228, 917281063, 2125852226, 996450942, 1871567999, 817292885, 305911019, 1663915494, 2129862591, 1286577839, 2028776637, 2091583730, 2087209709, 1638646442, 869251306, 241709899, 1747031448, 1511636664, 1711999127, 983598356, 1019765370, 687405323, 297737844, 257138559, 467599779, 998062456, 172439548, 1629062267, 715533125, 290286966, 417631819, 424218507, 1721965851, 1103325765, 1957071511, 259254706, 1537860726, 705326891, 524781644, 1707117195, 1807613669, 1624525273, 1851088584, 509737077, 332667776, 1824071405, 1408666800, 1064704490, 35808977, 1347680401, 680558317, 1292798449, 802777952, 1122917696, 740363591, 741671338, 1870016730, 942624937, 1390732956, 1551599879, 989783005, 149307564, 780551868, 1765392538, 621146211, 550535297, 1462431716, 2065413768, 1357125832, 1228936184, 737018326, 456906909, 416854905, 552905946, 1614932113, 1103672698, 742906171, 845405295, 889207986, 1146117865, 2143350293, 691772185, 204541799, 643194705, 2020904668, 1849321502, 1936768012, 1190548548, 199724377, 1470784387, 972224868, 790913078, 597771544, 285271059, 1980990581, 1992148297, 1710109392, 1803168639, 1188060928, 1580145475, 221534314, 1143011999, 2098150299, 1947906721, 1566939056, 1135339479, 1187991917, 960550597, 2071252371, 639007125, 1694658950, 1377091914, 1207244824, 1224353526, 1331419096, 134492280, 1222070497, 277577864, 1972425174, 1235530451, 892364372, 1038213930, 1257174184, 1473829326, 833871210, 301217552, 292371720, 129017245, 2142791190, 765156579, 1643196, 275487784, 399576143, 1746078469, 328583600, 1874337051, 1524903868, 352058610, 2113198767, 1664263450, 1909591035, 753825474, 118926782, 2120274450, 1187986319, 1717190346, 2074570773, 588192427, 1899249508, 803295075, 1548292027, 1278560985, 1397339391, 866951874, 1748178621, 410318738, 841581894, 546216710, 1210236938, 168180634, 1288173033, 406628433, 1803632622, 832188282, 87828332, 1101131533, 399235625, 763342479, 1426991571, 1835454544, 1898512300, 2102270782, 323580393, 1298486874, 1951354351, 1705178181, 66394412, 1811982139, 18278897, 842673453, 1090515544, 240500626, 1473990861, 1408654299, 2068126862, 371054448, 702240758, 460123462, 1336827681, 1778316122, 1336325903, 1885057859, 1531197438, 588071789, 335811945, 506477949, 1171269301, 1015550620, 321926426, 1788776320, 1010064936, 696723477, 2105963958, 743171572, 711239375, 1736023235, 2066516141, 1307270374, 1000266661, 1780827884, 1474220353, 1492478274, 314444722, 1583742457, 2014874146, 528496477, 1256843830, 1717442646, 321546919, 1842225327, 1796527983, 1211999600, 1376003499, 721980062, 1062562823, 1583089115, 1142995970, 1215340661, 1053626654, 2084021142, 952843415, 741636723, 706465519, 1646898278, 1248930852, 2016306176, 368712737, 894947422, 2106683020, 104665851, 974395308, 1489774208, 1755982808, 113164846, 1112422246, 1337686398, 871746252, 1059471587, 1456608554, 973364889, 1584315173, 230697360, 776119459, 1056282795, 1930652018, 2108658093, 1205975994, 898656576, 157243020, 906798246, 1843754906, 753111518, 2080631988, 1443150828, 291154012, 619046757, 1488669767, 2097325607, 1901727060, 1417902481, 758704672, 1113517958, 967363575, 1786671261, 2069854602, 520297782, 1303980903, 880075522, 1604402144, 971501040, 1795636893, 1273955678, 526872516, 1300615597, 429770546, 552416879, 338639352, 1901062773, 1439316682, 1646496062, 1582694876, 1648691285, 1464562974, 218664792, 905239428, 1839673967, 1597325476, 1832338743, 139082101, 270626603, 1459322844, 394273472, 648724477, 858561932, 54157625, 797143526, 1818604588, 629100957, 1618847659, 2129603948, 1360470130, 2128725514, 1579135429, 1838991815, 2083088599, 1258165450, 1274644880, 502229537, 376023249, 584452346, 363325163, 1327047546, 992859333, 1149959110, 2117971613, 1870008297, 423704861, 1245269632, 1341855737, 504763393, 1413189890, 435172306, 2108244780, 1610242127, 716213942, 459774480, 288139815, 1234802943, 1751732113, 790702247, 157120035, 1477348766, 1932973462, 1665032883, 920347605, 419810041, 1015300274, 1000677548, 1157857328, 2033492261, 1530995088, 774681407, 1544071122, 754489240, 1286070299, 1000415547, 672420620, 1977043317, 879349649, 1888424610, 904124561, 1007715301, 92940865, 1679956704, 1882124474, 1097902240, 910872289, 554185752, 1961288563, 1882158732, 1856059790, 1466457497, 1521117894, 235371132, 123196000, 1822912367, 1681978370, 1660193305, 1877429161, 1293243670, 1647348103, 676055774, 1138059723, 1976435018, 1680625457};
+            List list = new ArrayList<>(cap);
+            list.addAll(Arrays.asList(data));
+            return list;
         }
     }
 
     @Test
-    public void testPut() {
+    public void test() {
         Assert.expectTrue(list.size() == 1000);
         Assert.expectTrue(map.size() == 1000);
         for (int i = 0; i < list.size(); i++) {
             Integer k = list.get(i);
-            Assert.expectTrue(map.get(k).equals(String.valueOf(k)));
+            Assert.expectTrue(map.get(k).equals(k));
         }
-    }
 
-    @Test
-    public void testScan() {
         int i = 0;
         for (map.scan(); map.hasNext(); ) {
             i++;
-            Integer k = map.nextKey();
-            String  v = map.value();
-            Assert.expectTrue(v.equals(String.valueOf(k)));
+            Integer k = map.key();
+            Integer v = map.value();
+            Assert.expectTrue(k.equals(v));
             Assert.expectTrue(list.contains(k));
         }
         Assert.expectTrue(i == list.size());
+
+        int size = list.size();
+        for (int j = 0; j < list.size(); j++) {
+            _test_remove(list.get(j));
+        }
+        Assert.expectTrue(map.size() == 0);
+    }
+
+    void _test_remove(Integer k) {
+        Object mv = map.remove(k);
+        Assert.expectTrue(mv != null);
     }
 
     @Test
-    public void testRemove() {
-        int i    = 0;
-        int size = list.size();
+    public void testBigMap() {
+        int                   count   = 1024 * 1024;
+        IntMap       map     = new IntMap<>(count);
+        Map javaMap = new HashMap<>();
+        Random                random  = new Random();
+        for (int i = 0; i < count; i++) {
+            Integer v = random.nextInt(Integer.MAX_VALUE);
+            map.put(v, v);
+            javaMap.put(v, v);
+        }
+        int map_count = 0;
         for (map.scan(); map.hasNext(); ) {
-            i++;
-            Integer k = map.nextKey();
-            String  v = map.value();
-            Assert.expectTrue(v.equals(String.valueOf(k)));
-            Assert.expectTrue(list.contains(k));
-            if (k % 2 == 0) {
-                map.remove(k);
-                list.remove(k);
-            }
+            map_count++;
         }
-        Assert.expectTrue(i == size);
-        testScan();
+        logger.info("map_count: {}, javaMap_count: {}", map_count, javaMap.size());
+        Assert.expectTrue(map_count == javaMap.size());
     }
 
+
 }
diff --git a/firenio-test/src/main/java/test/others/TestIntMap1.java b/firenio-test/src/main/java/test/others/TestIntMap1.java
new file mode 100644
index 000000000..c01afcd09
--- /dev/null
+++ b/firenio-test/src/main/java/test/others/TestIntMap1.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.others;
+
+import io.netty.util.collection.IntObjectHashMap;
+
+import com.firenio.collection.IntMap;
+import com.firenio.log.LoggerFactory;
+
+/**
+ * @author: wangkai
+ **/
+public class TestIntMap1 {
+
+    public static void main(String[] args) {
+        LoggerFactory.setEnableSLF4JLogger(false);
+        //        testNettyMap();
+        testMyMap();
+    }
+
+    static void testNettyMap() {
+
+        IntObjectHashMap map = new IntObjectHashMap(8);
+
+        map.put(7, "7");
+        map.put(15, "15");
+
+
+        System.out.println(map);
+
+    }
+
+    static void testMyMap() {
+        int            test    = 1005;
+        String         debug   = "remove 981";
+        IntMap map     = new IntMap<>(256);
+        String         string  = "put 151\n" + "remove 152";
+        String[]       actions = string.split("\n");
+        boolean        mark    = false;
+        for (int i = 0; i < actions.length; i++) {
+            String   action = actions[i];
+            String[] ss     = action.split(" ");
+            String   sid    = ss[1];
+            int      id     = Integer.parseInt(sid);
+            if (id == test) {
+                mark = true;
+                System.out.println(id);
+            }
+            if (action.equals(debug)) {
+                System.out.println(id);
+            }
+            if ("put".equals(ss[0])) {
+                map.put(id, sid);
+            } else {
+                map.remove(id);
+            }
+            System.out.println(action);
+            if (mark) {
+                if (map.get(test) == null) {
+                    System.out.println(".........................");
+                    return;
+                }
+            }
+        }
+        System.out.println(map.get(test));
+    }
+
+}
diff --git a/firenio-test/src/main/java/test/others/TestMask.java b/firenio-test/src/main/java/test/others/TestMask.java
index dce525c01..50ad4cdd4 100644
--- a/firenio-test/src/main/java/test/others/TestMask.java
+++ b/firenio-test/src/main/java/test/others/TestMask.java
@@ -26,16 +26,16 @@ public class TestMask {
 
     public static void main(String[] args) {
         ByteBuf buf  = ByteBuf.wrap("hello word!".getBytes());
-        byte    mask = (byte) buf.remaining();
+        byte    mask = (byte) buf.readableBytes();
         mask(buf, mask);
-        System.out.println(new String(buf.getBytes()));
-        buf.position(0);
+        System.out.println(new String(buf.readBytes()));
+        buf.readIndex(0);
         mask(buf, mask);
-        System.out.println(new String(buf.getBytes()));
+        System.out.println(new String(buf.readBytes()));
     }
 
     public static void mask(ByteBuf src, byte m) {
-        ByteBuffer buf = src.nioBuffer();
+        ByteBuffer buf = src.nioWriteBuffer();
         int        p   = buf.position();
         int        l   = buf.limit();
         for (; p < l; p++) {
diff --git a/firenio-test/src/main/java/test/others/TestNettyByteBuf.java b/firenio-test/src/main/java/test/others/TestNettyByteBuf.java
new file mode 100644
index 000000000..bfbeb0bbc
--- /dev/null
+++ b/firenio-test/src/main/java/test/others/TestNettyByteBuf.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.others;
+
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+
+import com.firenio.common.Util;
+
+/**
+ * @author: wangkai
+ **/
+public class TestNettyByteBuf {
+
+    static volatile ByteBuf buf;
+
+    public static void main(String[] args) {
+
+        ByteBufAllocator a = ByteBufAllocator.DEFAULT;
+
+        Util.exec(() ->{
+            buf = a.buffer(16);
+        });
+
+        Util.exec(() ->{
+            buf.release();
+        });
+
+        System.out.println(buf);
+
+
+    }
+
+
+}
diff --git a/firenio-test/src/main/java/test/others/TestShutdown.java b/firenio-test/src/main/java/test/others/TestShutdown.java
new file mode 100644
index 000000000..7ca71156d
--- /dev/null
+++ b/firenio-test/src/main/java/test/others/TestShutdown.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.others;
+
+import java.nio.ByteBuffer;
+
+import com.firenio.common.Unsafe;
+import com.firenio.log.Logger;
+import com.firenio.log.LoggerFactory;
+
+/**
+ * @author: wangkai
+ **/
+public class TestShutdown {
+
+
+    public static void main(String[] args) {
+        LoggerFactory.setEnableSLF4JLogger(false);
+
+        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+            System.out.println("shutdown....");
+        }));
+        System.out.println("start..");
+        long address = Unsafe.allocate(1);
+        Unsafe.free(address);
+
+        Unsafe.putInt(address,100);
+        System.out.println("put address success..");
+
+        ByteBuffer buf = ByteBuffer.allocateDirect(100);
+        Unsafe.freeByteBuffer(buf);
+        buf.putLong(100);
+        System.out.println("put buffer success..");
+
+        Unsafe.putInt(-1,100);
+        System.out.println("put address -1 success..");
+
+        Unsafe.putInt(0,100);
+        System.out.println("put address 0 success..");
+
+        System.out.println("end....");
+
+    }
+
+
+
+
+}
diff --git a/firenio-test/src/main/java/test/others/TestScsp.java b/firenio-test/src/main/java/test/others/TestVolatile.java
similarity index 54%
rename from firenio-test/src/main/java/test/others/TestScsp.java
rename to firenio-test/src/main/java/test/others/TestVolatile.java
index 476309ac0..e73998862 100644
--- a/firenio-test/src/main/java/test/others/TestScsp.java
+++ b/firenio-test/src/main/java/test/others/TestVolatile.java
@@ -15,31 +15,23 @@
  */
 package test.others;
 
-import com.firenio.common.Util;
-import com.firenio.concurrent.ScmpLinkedQueue;
-
 /**
- * @author wangkai
- */
-public class TestScsp {
-
-    public static void main(String[] args) throws Exception {
-
-        ScmpLinkedQueue queue = new ScmpLinkedQueue<>();
+ * @author: wangkai
+ **/
+public class TestVolatile {
 
-        for (int i = 0; i < 4; i++) {
-            Util.exec(() -> {
-                for (int j = 0; j < 32; j++) {
-                    queue.offer(String.valueOf(j));
-                }
-            });
-        }
+    static boolean running = true;
 
-        //        Util.sleep(100);
-        System.out.println("size:" + queue.size());
-        for (; queue.size() > 0; ) {
-            System.out.println(queue.poll());
-        }
+    public static void main(String[] args) throws Exception {
+        new Thread(() -> {
+            for (; running; ) {
+                //Thread.yield();
+            }
+            System.out.println("worker stop");
+        }).start();
+        Thread.sleep(500);
+        running = false;
+        System.out.println("set running false");
     }
 
 }
diff --git a/firenio-test/src/main/java/test/others/TestVolatile2.java b/firenio-test/src/main/java/test/others/TestVolatile2.java
new file mode 100644
index 000000000..2d93c35f3
--- /dev/null
+++ b/firenio-test/src/main/java/test/others/TestVolatile2.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.others;
+
+/**
+ * @author: wangkai
+ **/
+public class TestVolatile2 {
+
+    static          boolean running = true;
+    static volatile int     mem_bar = 0;
+
+    public static void main(String[] args) throws Exception {
+        new Thread(() -> {
+            int temp = 0;
+            for (; running; ) {
+                temp = mem_bar;
+            }
+            System.out.println("worker stop");
+        }).start();
+        Thread.sleep(500);
+        running = false;
+        System.out.println("set running false");
+    }
+
+}
diff --git a/firenio-test/src/main/java/test/others/algorithm/BubbleSort.java b/firenio-test/src/main/java/test/others/algorithm/BubbleSort.java
index 9e0371a3f..f3e1b02b5 100644
--- a/firenio-test/src/main/java/test/others/algorithm/BubbleSort.java
+++ b/firenio-test/src/main/java/test/others/algorithm/BubbleSort.java
@@ -25,16 +25,10 @@
 public class BubbleSort {
 
     public static void main(String[] args) {
-
-        int[] array = new int[30];
-        for (int i = 0; i < array.length; i++) {
-            array[i] = new Random().nextInt(30);
-        }
-
-        Util.printArray(array);
+        int[] array = TestSort.random_array();
+        System.out.println(Util.arrayToString(array));
         sort(array);
-        Util.printArray(array);
-
+        System.out.println(Util.arrayToString(array));
     }
 
     public static void sort(int[] array) {
diff --git a/firenio-test/src/main/java/test/others/algorithm/ByteArray.java b/firenio-test/src/main/java/test/others/algorithm/ByteArray.java
deleted file mode 100644
index a85ba9f55..000000000
--- a/firenio-test/src/main/java/test/others/algorithm/ByteArray.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright 2015 The FireNio Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package test.others.algorithm;
-
-/**
- * @author wangkai
- */
-public class ByteArray {
-
-    private byte[] data;
-
-    private int length;
-
-    private int off;
-
-    public ByteArray() {}
-
-    public ByteArray(byte[] data, int off, int length) {
-        this.data = data;
-        this.off = off;
-        this.length = length;
-    }
-
-    private static boolean greater(ByteArray b1, ByteArray b2) {
-        int len = b1.getLength();
-        for (int i = 0; i < len; i++) {
-            byte b11 = b1.getByte(i);
-            byte b22 = b2.getByte(i);
-            if (b11 != b22) {
-                return b11 > b22;
-            }
-        }
-        return false;
-    }
-
-    private static boolean greaterOrEquals(ByteArray b1, ByteArray b2) {
-        int len = b1.getLength();
-        for (int i = 0; i < len; i++) {
-            byte b11 = b1.getByte(i);
-            byte b22 = b2.getByte(i);
-            if (b11 != b22) {
-                return b11 > b22;
-            }
-        }
-        return true;
-    }
-
-    private static boolean lessOrEquals(ByteArray b1, ByteArray b2) {
-        int len = b1.getLength();
-        for (int i = 0; i < len; i++) {
-            byte b11 = b1.getByte(i);
-            byte b22 = b2.getByte(i);
-            if (b11 != b22) {
-                return b11 < b22;
-            }
-        }
-        return true;
-    }
-
-    public byte getByte(int pos) {
-        return data[ix(pos)];
-    }
-
-    public byte[] getData() {
-        return data;
-    }
-
-    public int getLength() {
-        return length;
-    }
-
-    public int getOff() {
-        return off;
-    }
-
-    public boolean greater(ByteArray o) {
-        if (getLength() > o.getLength()) {
-            return true;
-        }
-        if (getLength() < o.getLength()) {
-            return false;
-        }
-        return greater(this, o);
-    }
-
-    public boolean greaterOrEquals(ByteArray o) {
-        if (getLength() > o.getLength()) {
-            return true;
-        }
-        if (getLength() < o.getLength()) {
-            return false;
-        }
-        return greaterOrEquals(this, o);
-    }
-
-    private int ix(int pos) {
-        return off + pos;
-    }
-
-    public boolean lessOrEquals(ByteArray o) {
-        if (getLength() > o.getLength()) {
-            return false;
-        }
-        if (getLength() < o.getLength()) {
-            return true;
-        }
-        return lessOrEquals(this, o);
-    }
-
-    public void setData(byte[] data) {
-        this.data = data;
-    }
-
-    public void setLength(int length) {
-        this.length = length;
-    }
-
-    public void setOff(int off) {
-        this.off = off;
-    }
-
-    public String toString1() {
-        return new String(data, off, length);
-    }
-}
diff --git a/firenio-test/src/main/java/test/others/algorithm/InsertSort.java b/firenio-test/src/main/java/test/others/algorithm/InsertSort.java
new file mode 100644
index 000000000..159fc68c0
--- /dev/null
+++ b/firenio-test/src/main/java/test/others/algorithm/InsertSort.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.others.algorithm;
+
+/**
+ * @author: wangkai
+ **/
+public class InsertSort {
+
+    public static void main(String[] args) {
+        TestSort.test(InsertSort::sort, 10);
+        //        TestSort.test_load(InsertSort::sort, 1024 * 32, 16);
+        TestSort.test_load(InsertSort::sort, 16, 1024 * 1024 * 8);
+    }
+
+    public static void sort(int[] array, int off, int end) {
+        if (end - off < 2) {
+            return;
+        }
+        int s0 = array[off + 0];
+        int s1 = array[off + 1];
+        if (s1 < s0) {
+            array[off + 0] = s1;
+            array[off + 1] = s0;
+        }
+        direct_sort(array, off, end);
+    }
+
+    public static void sort(int[] array) {
+        sort(array, 0, array.length);
+    }
+
+    static void move_des(int[] array, int j, int i) {
+        for (int k = i; k > j; k--) {
+            array[k] = array[k - 1];
+        }
+    }
+
+    static void direct_sort(int[] array, int off, int end) {
+        for (int i = off + 2; i < end; i++) {
+            int temp    = array[i];
+            int mid_idx = (i + off) >>> 1;
+            int j       = temp < array[mid_idx] ? off : mid_idx;
+            for (; j < i; j++) {
+                if (temp < array[j]) {
+                    move_des(array, j, i);
+                    array[j] = temp;
+                    break;
+                }
+            }
+        }
+    }
+
+    static void half_sort(int[] array, int off, int end) {
+        for (int i = off + 2; i < end; i++) {
+            int temp = array[i];
+            int j    = half_find(array, off, i, temp);
+            if (j < i) {
+                move_des(array, j, i);
+                array[j] = temp;
+            }
+        }
+    }
+
+    static int half_find(int[] array, int low, int high, int value) {
+        int mid = high >>> 1;
+        for (; ; ) {
+            int temp = array[mid];
+            if (value > temp) {
+                low = mid;
+            } else if (temp == value) {
+                return mid;
+            } else {
+                high = mid;
+            }
+            if (high - low == 1) {
+                if (value < array[low]) {
+                    return low;
+                } else {
+                    return high;
+                }
+            }
+            mid = (low + high) >>> 1;
+        }
+    }
+
+    static void move_aes(int[] array, int j, int i) {
+        int t1 = array[j];
+        int t2 = array[j + 1];
+        for (int k = j + 1; k < i; k++) {
+            t2 = array[k];
+            array[k] = t1;
+            t1 = t2;
+        }
+        array[i] = t1;
+    }
+
+}
diff --git a/firenio-test/src/main/java/test/others/algorithm/KMPUtil.java b/firenio-test/src/main/java/test/others/algorithm/KMPUtil.java
deleted file mode 100644
index 36cab87a3..000000000
--- a/firenio-test/src/main/java/test/others/algorithm/KMPUtil.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright 2015 The FireNio Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package test.others.algorithm;
-
-import com.firenio.collection.IntArray;
-import com.firenio.common.Util;
-
-//关键字:前缀,后缀,部分匹配表
-public class KMPUtil {
-
-    private char[] match_array;
-
-    private int[] match_table;
-
-    private String match_value;
-
-    public KMPUtil(String value) {
-        this.initialize(value);
-    }
-
-    public static void main(String[] args) {
-
-        String s1 = "1111111111111111111211111111112111121111211111111";
-
-        String match = "1112";
-
-        KMPUtil kmp = new KMPUtil(match);
-
-        System.out.println(kmp.match_all(s1));
-
-    }
-
-    private void initialize(String value) {
-        if (Util.isNullOrBlank(value)) {
-            throw new IllegalArgumentException("null value");
-        }
-        this.match_value = value;
-        this.match_array = match_value.toCharArray();
-        this.match_table = new int[match_value.length()];
-        this.initialize_part_match_table();
-    }
-
-    private void initialize_part_match_table() {
-        int length = this.match_value.length();
-        // 直接从两位开始比较
-        for (int i = 2; i < length; i++) {
-            match_table[i] = initialize_part_match_table0(match_array, i);
-        }
-    }
-
-    private int initialize_part_match_table0(char[] array, int length) {
-        int e = 0;
-        WORD:
-        for (int i = 1; i < length; i++) {
-            int t = 0;
-            int p = 0;
-            int s = length - i;
-            for (int j = 0; j < i; j++) {
-                if (array[p++] != array[s++]) {
-                    continue WORD;
-                }
-                t++;
-            }
-            e = t;
-        }
-        return e;
-    }
-
-    public int match(String value) {
-        return match(value, 0);
-    }
-
-    public int match(String value, int begin) {
-        if (Util.isNullOrBlank(value) || begin < 0) {
-            return -1;
-        }
-        if (value.length() - begin < this.match_array.length) {
-            return -1;
-        }
-        int    source_length = value.length();
-        int    index         = begin;
-        int    match_length  = this.match_array.length;
-        char[] match_array   = this.match_array;
-        int[]  match_table   = this.match_table;
-        LOOP:
-        for (; index < source_length; ) {
-            for (int i = 0; i < match_length; i++) {
-                if (value.charAt(index + i) != match_array[i]) {
-                    if (i == 0) {
-                        index++;
-                    } else {
-                        index += (i - match_table[i]);
-                    }
-                    continue LOOP;
-                }
-            }
-            return index;
-        }
-        return -1;
-    }
-
-    public IntArray match_all(String value) {
-        if (Util.isNullOrBlank(value)) {
-            return null;
-        }
-        if (value.length() < match_value.length()) {
-            return null;
-        }
-        IntArray matchs = new IntArray();
-        if (value.equals(match_value)) {
-            matchs.add(0);
-            return matchs;
-        }
-        int    source_length = value.length();
-        int    index         = 0;
-        int    match_length  = this.match_array.length;
-        char[] match_array   = this.match_array;
-        int[]  match_table   = this.match_table;
-        LOOP:
-        for (; index < source_length; ) {
-            if (source_length - index < match_length) {
-                break;
-            }
-            for (int i = 0; i < match_length; i++) {
-                if (value.charAt(index + i) != match_array[i]) {
-                    if (i == 0) {
-                        index++;
-                    } else {
-                        index += (i - match_table[i]);
-                    }
-                    continue LOOP;
-                }
-            }
-            matchs.add(index);
-            index += match_length;
-        }
-        return matchs;
-    }
-}
diff --git a/firenio-test/src/main/java/test/others/algorithm/Lz4CompressedInputStream.java b/firenio-test/src/main/java/test/others/algorithm/Lz4CompressedInputStream.java
index 083b3f04d..4ca5434f1 100644
--- a/firenio-test/src/main/java/test/others/algorithm/Lz4CompressedInputStream.java
+++ b/firenio-test/src/main/java/test/others/algorithm/Lz4CompressedInputStream.java
@@ -20,7 +20,7 @@ public class Lz4CompressedInputStream extends InputStream {
     public Lz4CompressedInputStream(InputStream inputStream, int bufSize) {
         this.inputStream = inputStream;
         this.buf = ByteBuf.heap(bufSize);
-        this.buf.limit(0);
+        this.buf.writeIndex(0);
     }
 
     public static int read(ByteBuf dst, InputStream src) throws IOException {
@@ -29,23 +29,23 @@ public static int read(ByteBuf dst, InputStream src) throws IOException {
 
     public static int read(ByteBuf dst, InputStream src, long limit) throws IOException {
         byte[] array = dst.array();
-        if (!dst.hasRemaining()) {
+        if (!dst.hasReadableBytes()) {
             int read = (int) Math.min(limit, dst.capacity());
             int len  = src.read(array, 0, read);
             if (len > 0) {
-                dst.position(0);
-                dst.limit(len);
+                dst.readIndex(0);
+                dst.writeIndex(len);
             }
             return len;
         }
-        int remaining = dst.remaining();
-        System.arraycopy(array, dst.position(), array, 0, remaining);
-        dst.position(0);
-        dst.limit(remaining);
+        int remaining = dst.readableBytes();
+        System.arraycopy(array, dst.readIndex(), array, 0, remaining);
+        dst.readIndex(0);
+        dst.writeIndex(remaining);
         int read = (int) Math.min(limit, dst.capacity() - remaining);
         int len  = src.read(array, remaining, read);
         if (len > 0) {
-            dst.limit(remaining + len);
+            dst.writeIndex(remaining + len);
         }
         return len;
     }
@@ -69,9 +69,9 @@ public int read(byte[] b) throws IOException {
     public int read(byte[] b, int off, int len) throws IOException {
         ByteBuf buf        = this.buf;
         byte[]  readBuffer = buf.array();
-        int     limit      = buf.limit();
-        int     offset     = buf.position();
-        if (buf.remaining() <= 4) {
+        int     limit      = buf.writeIndex();
+        int     offset     = buf.readIndex();
+        if (buf.readableBytes() <= 4) {
             if (!hasRemaining) {
                 return -1;
             }
@@ -87,7 +87,7 @@ public int read(byte[] b, int off, int len) throws IOException {
             read(buf);
             return read(b, off, len);
         }
-        buf.position(offset + _len);
+        buf.readIndex(offset + _len);
         return Lz4RawDecompressor.decompress(readBuffer, offset, _len, b, off, len);
     }
 
diff --git a/firenio-test/src/main/java/test/others/algorithm/Lz4RawCompressor.java b/firenio-test/src/main/java/test/others/algorithm/Lz4RawCompressor.java
index 0b49ed5c4..fba726511 100644
--- a/firenio-test/src/main/java/test/others/algorithm/Lz4RawCompressor.java
+++ b/firenio-test/src/main/java/test/others/algorithm/Lz4RawCompressor.java
@@ -77,7 +77,7 @@ public static int compress(final Object inputBase, final long inputAddress, fina
         long anchor = input;
 
         // First Byte
-        // put position in hash
+        // put readIndex in hash
         table[hash(Unsafe.getLong(inputBase, input), mask)] = (int) (input - inputAddress);
 
         input++;
@@ -102,11 +102,11 @@ public static int compress(final Object inputBase, final long inputAddress, fina
                     return (int) (emitLastLiteral(outputBase, output, inputBase, anchor, inputLimit - anchor) - outputAddress);
                 }
 
-                // get position on hash
+                // get readIndex on hash
                 matchIndex = inputAddress + table[hash];
                 nextHash = hash(Unsafe.getLong(inputBase, nextInputIndex), mask);
 
-                // put position on hash
+                // put readIndex on hash
                 table[hash] = (int) (input - inputAddress);
             } while (Unsafe.getInt(inputBase, matchIndex) != Unsafe.getInt(inputBase, input) || matchIndex + MAX_DISTANCE < input);
 
@@ -140,7 +140,7 @@ public static int compress(final Object inputBase, final long inputAddress, fina
                 long position = input - 2;
                 table[hash(Unsafe.getLong(inputBase, position), mask)] = (int) (position - inputAddress);
 
-                // Test next position
+                // Test next readIndex
                 int hash = hash(Unsafe.getLong(inputBase, input), mask);
                 matchIndex = inputAddress + table[hash];
                 table[hash] = (int) (input - inputAddress);
diff --git a/firenio-test/src/main/java/test/others/algorithm/QuickSort.java b/firenio-test/src/main/java/test/others/algorithm/QuickSort.java
index 1bf8400d8..8e2cb928d 100644
--- a/firenio-test/src/main/java/test/others/algorithm/QuickSort.java
+++ b/firenio-test/src/main/java/test/others/algorithm/QuickSort.java
@@ -18,6 +18,7 @@
 import java.util.Random;
 
 import com.firenio.common.Util;
+import com.firenio.log.LoggerFactory;
 
 /**
  * @author wangkai
@@ -26,19 +27,13 @@ public class QuickSort {
 
     public static void main(String[] args) {
 
-        int[] array = new int[30];
-        for (int i = 0; i < array.length; i++) {
-            array[i] = new Random().nextInt(30);
-        }
-
-        Util.printArray(array);
-        sort(array, 0, 29);
-        Util.printArray(array);
+        TestSort.test(QuickSort::sort, 10);
+                TestSort.test_load(QuickSort::sort, 1024 * 32, 1024);
+//        TestSort.test_load(QuickSort::sort, 16, 1024 * 1024 * 8);
 
     }
 
     private static int partition(int[] array, int low, int high) {
-        //三数取中
         int mid = low + (high - low) / 2;
         if (array[mid] > array[high]) {
             swap(array, mid, high);
@@ -49,6 +44,7 @@ private static int partition(int[] array, int low, int high) {
         if (array[mid] > array[low]) {
             swap(array, mid, low);
         }
+
         int key = array[low];
 
         while (low < high) {
@@ -65,6 +61,10 @@ private static int partition(int[] array, int low, int high) {
         return high;
     }
 
+    public static void sort(int[] array) {
+        sort(array, 0, array.length - 1);
+    }
+
     public static void sort(int[] array, int low, int high) {
         if (low >= high) {
             return;
diff --git a/firenio-test/src/main/java/test/others/algorithm/QuickSort1.java b/firenio-test/src/main/java/test/others/algorithm/QuickSort1.java
new file mode 100644
index 000000000..3044872b9
--- /dev/null
+++ b/firenio-test/src/main/java/test/others/algorithm/QuickSort1.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.others.algorithm;
+
+/**
+ * @author wangkai
+ */
+public class QuickSort1 {
+
+    public static void main(String[] args) {
+
+        TestSort.test(QuickSort1::sort, new int[]{9, 17, 19, 8, 3, 15, 17, 14, 14, 5});
+        //        TestSort.test(QuickSort1::sort, new int[]{4, 3, 5});
+        TestSort.test_load(QuickSort1::sort, 1024 * 32, 1024);
+
+    }
+
+    private static int p_sort(int[] array, int low, int high) {
+        int mid = low + (high - low) / 2;
+        int key = (array[low] + array[mid] + array[high]) / 3;
+        for (; low < high; ) {
+            while (array[high] >= key && high > low) {
+                high--;
+            }
+            while (array[low] <= key && high > low) {
+                low++;
+            }
+            if (low < high) {
+                swap(array, low, high);
+            } else {
+                break;
+            }
+        }
+        return high;
+    }
+
+    public static void sort(int[] array) {
+        sort(array, 0, array.length);
+    }
+
+    public static void sort(int[] array, int low, int high) {
+        if (high - low < 8) {
+            InsertSort.sort(array, low, high);
+        } else {
+            int index = p_sort(array, low, high - 1) + 1;
+            sort(array, low, index);
+            sort(array, index, high);
+        }
+    }
+
+    private static void swap(int[] array, int a, int b) {
+        int temp = array[a];
+        array[a] = array[b];
+        array[b] = temp;
+    }
+
+}
diff --git a/firenio-test/src/main/java/test/others/algorithm/QuickSort2.java b/firenio-test/src/main/java/test/others/algorithm/QuickSort2.java
index 87c3713f7..2723b5742 100644
--- a/firenio-test/src/main/java/test/others/algorithm/QuickSort2.java
+++ b/firenio-test/src/main/java/test/others/algorithm/QuickSort2.java
@@ -20,50 +20,58 @@
  */
 public class QuickSort2 {
 
-    private static int partition(ByteArray[] array, int low, int high) {
-        //三数取中
+    public static void main(String[] args) {
+
+        TestSort.test(QuickSort2::sort, 16);
+        TestSort.test_load(QuickSort2::sort, 1024 * 32, 1024);
+    }
+
+    private static int partition(int[] array, int low, int high) {
         int mid = low + (high - low) / 2;
-        if (array[mid].greater(array[high])) {
-            swap(array[mid], array[high]);
+        if (array[mid] > array[high]) {
+            swap(array, mid, high);
         }
-        if (array[low].greater(array[high])) {
-            swap(array[low], array[high]);
+        if (array[low] > array[high]) {
+            swap(array, low, high);
         }
-        if (array[mid].greater(array[low])) {
-            swap(array[mid], array[low]);
+        if (array[mid] > array[low]) {
+            swap(array, mid, low);
         }
-        ByteArray key = array[low];
+
+        int key = array[low];
 
         while (low < high) {
-            while (array[high].greaterOrEquals(key) && high > low) {
+            while (array[high] >= key && high > low) {
                 high--;
             }
             array[low] = array[high];
-            while (array[low].lessOrEquals(key) && high > low) {
+            while (array[low] <= key && high > low) {
                 low++;
             }
             array[high] = array[low];
         }
-        array[low] = key;//这里low
+        array[low] = key;
         return high;
     }
 
-    public static void sort(ByteArray[] array, int low, int high) {
-        if (low >= high) {
-            return;
+    public static void sort(int[] array) {
+        sort(array, 0, array.length - 1);
+    }
+
+    public static void sort(int[] array, int low, int high) {
+        if (high - low < 8) {
+            InsertSort.sort(array, low, high + 1);
+        } else {
+            int index = partition(array, low, high);
+            sort(array, low, index - 1);
+            sort(array, index + 1, high);
         }
-        int index = partition(array, low, high);
-        sort(array, low, index - 1);
-        sort(array, index + 1, high);
     }
 
-    private static void swap(ByteArray a, ByteArray b) {
-        int tmpOff = a.getOff();
-        int tmpLen = a.getLength();
-        a.setLength(b.getLength());
-        a.setOff(b.getOff());
-        b.setLength(tmpLen);
-        b.setOff(tmpOff);
+    private static void swap(int[] array, int a, int b) {
+        int temp = array[a];
+        array[a] = array[b];
+        array[b] = temp;
     }
 
 }
diff --git a/firenio-test/src/main/java/test/others/algorithm/RSAUtil.java b/firenio-test/src/main/java/test/others/algorithm/RSAUtil.java
deleted file mode 100644
index 1809a73ea..000000000
--- a/firenio-test/src/main/java/test/others/algorithm/RSAUtil.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright 2015 The FireNio Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package test.others.algorithm;
-
-import java.io.File;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.RSAPrivateKeySpec;
-import java.security.spec.RSAPublicKeySpec;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.crypto.Cipher;
-
-import com.firenio.common.FileUtil;
-import com.firenio.common.Util;
-
-public class RSAUtil {
-
-    private static KeyFactory keyFactory;
-
-    static {
-        try {
-            keyFactory = KeyFactory.getInstance("RSA");
-        } catch (NoSuchAlgorithmException e) {
-        }
-    }
-
-    /**
-     * 私钥解密
-     *
-     * @param bytes
-     * @param privateKey
-     * @return
-     * @throws Exception
-     */
-    public static byte[] decryptByPrivateKey(byte[] bytes, RSAPrivateKey privateKey) throws Exception {
-        Cipher cipher = Cipher.getInstance("RSA");
-        cipher.init(Cipher.DECRYPT_MODE, privateKey);
-        // 模长
-        int key_len = privateKey.getModulus().bitLength() / 8;
-        // 如果密文长度大于模长则要分组解密
-        List arrays = splitArray(bytes, key_len);
-        ByteBuffer   buffer = ByteBuffer.allocate(arrays.size() * (key_len - 11));
-        for (byte[] arr : arrays) {
-            byte[] marr = cipher.doFinal(arr);
-            buffer.put(marr);
-        }
-        byte[] r = new byte[buffer.position()];
-        buffer.flip();
-        buffer.get(r);
-        return r;
-    }
-
-    /**
-     * 公钥加密
-     *
-     * @param data
-     * @param publicKey
-     * @return
-     * @throws Exception
-     */
-    public static byte[] encryptByPublicKey(byte[] data, RSAPublicKey publicKey) throws Exception {
-        Cipher cipher = Cipher.getInstance("RSA");
-        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
-        // 模长
-        int key_len = publicKey.getModulus().bitLength() / 8;
-        // 加密数据长度 <= 模长-11
-        List datas  = splitArray(data, key_len - 11);
-        ByteBuffer   buffer = ByteBuffer.allocate(key_len * datas.size());
-        // 如果明文长度大于模长-11则要分组加密
-        for (byte[] s : datas) {
-            byte[] array = cipher.doFinal(s);
-            buffer.put(array);
-        }
-        return buffer.array();
-    }
-
-    public static void generateKeys(String file, int length) throws NoSuchAlgorithmException, IOException {
-        RSAKeys keys = RSAUtil.getKeys(length);
-        // 生成公钥和私钥
-        RSAPublicKey  publicKey        = keys.getPublicKey();
-        RSAPrivateKey privateKey       = keys.getPrivateKey();
-        File          publicKeyFile    = new File(file + "/public.rsa");
-        String        publicKeyString  = publicKey.toString();
-        File          privateKeyFile   = new File(file + "/private.rsa");
-        String        privateKeyString = privateKey.toString();
-        FileUtil.writeByFile(publicKeyFile, publicKeyString);
-        FileUtil.writeByFile(privateKeyFile, privateKeyString);
-        System.out.println("Public RSA File:" + publicKeyFile.getCanonicalPath());
-        System.out.println(publicKeyString);
-        System.out.println();
-        System.out.println("Private RSA File:" + privateKeyFile.getCanonicalPath());
-        System.out.println(privateKeyString);
-    }
-
-    /**
-     * 生成公钥和私钥
-     *
-     * @param length 1024 ...
-     * @throws NoSuchAlgorithmException
-     */
-    public static RSAKeys getKeys(int length) throws NoSuchAlgorithmException {
-        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
-        keyPairGen.initialize(length);
-        KeyPair keyPair = keyPairGen.generateKeyPair();
-        RSAKeys keys    = new RSAKeys();
-        keys.publicKey = (RSAPublicKey) keyPair.getPublic();
-        keys.privateKey = (RSAPrivateKey) keyPair.getPrivate();
-        return keys;
-    }
-
-    /**
-     * 使用模和指数生成RSA私钥
-     * 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
-     * /None/NoPadding】
-     *
-     * @param modulus  模
-     * @param exponent 指数
-     * @return
-     */
-    public static RSAPrivateKey getPrivateKey(String modulus, String exponent) {
-        try {
-            BigInteger        b1      = new BigInteger(modulus);
-            BigInteger        b2      = new BigInteger(exponent);
-            RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(b1, b2);
-            return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
-        } catch (Exception e) {
-            throw new RuntimeException(e.getMessage(), e);
-        }
-    }
-
-    /**
-     * 使用模和指数生成RSA公钥
-     * 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA
-     * /None/NoPadding】
-     *
-     * @param modulus  模
-     * @param exponent 指数
-     * @return
-     */
-    public static RSAPublicKey getPublicKey(String modulus, String exponent) {
-        try {
-            BigInteger       b1         = new BigInteger(modulus);
-            BigInteger       b2         = new BigInteger(exponent);
-            KeyFactory       keyFactory = KeyFactory.getInstance("RSA");
-            RSAPublicKeySpec keySpec    = new RSAPublicKeySpec(b1, b2);
-            return (RSAPublicKey) keyFactory.generatePublic(keySpec);
-        } catch (Exception e) {
-            throw new RuntimeException(e.getMessage(), e);
-        }
-    }
-
-    public static RSAPrivateKey getRsaPrivateKey(String content) {
-        if (Util.isNullOrBlank(content)) {
-            throw new IllegalArgumentException("null content");
-        }
-        Map map      = parseRSAFromContent(content);
-        String              modulus  = map.get("modulus");
-        String              exponent = map.get("private exponent");
-        return getPrivateKey(modulus, exponent);
-    }
-
-    public static RSAPublicKey getRsaPublicKey(String content) {
-        if (Util.isNullOrBlank(content)) {
-            throw new IllegalArgumentException("null content");
-        }
-        Map map      = parseRSAFromContent(content);
-        String              modulus  = map.get("modulus");
-        String              exponent = map.get("public exponent");
-        return getPublicKey(modulus, exponent);
-    }
-
-    public static void main(String[] args) throws Exception {
-        RSAKeys keys = RSAUtil.getKeys(1024);
-        // 生成公钥和私钥
-        RSAPublicKey  publicKey  = keys.getPublicKey();
-        RSAPrivateKey privateKey = keys.getPrivateKey();
-        // 模
-        String modulus = publicKey.getModulus().toString();
-        // 公钥指数
-        String public_exponent = publicKey.getPublicExponent().toString();
-        // 私钥指数
-        String private_exponent = privateKey.getPrivateExponent().toString();
-        // 明文
-        String ming = "你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好";
-        // ming = "22ttt2aasdaaaaaasdasddw";
-        // 使用模和指数生成公钥和私钥
-        RSAPublicKey  pubKey = RSAUtil.getPublicKey(modulus, public_exponent);
-        RSAPrivateKey priKey = RSAUtil.getPrivateKey(modulus, private_exponent);
-        // 加密后的密文
-        byte[] mi = RSAUtil.encryptByPublicKey(ming.getBytes(Util.GBK), pubKey);
-        System.out.println("mi.length:" + mi.length);
-        // 解密后的明文
-        ming = new String(RSAUtil.decryptByPrivateKey(mi, priKey), Util.GBK);
-        System.err.println("明文:" + ming);
-    }
-
-    private static Map parseRSAFromContent(String content) {
-        String[]            lines = content.split("\n");
-        Map map   = new HashMap<>();
-        for (int i = 1; i < lines.length; i++) {
-            String[] array = lines[i].split(":");
-            if (array.length != 2) {
-                continue;
-            }
-            String name  = array[0].trim().replace("\r", "");
-            String value = array[1].trim().replace("\r", "");
-            map.put(name, value);
-        }
-        return map;
-    }
-
-    /**
-     * 拆分字符串
-     */
-    private static List splitArray(byte[] array, int len) {
-        int          length = array.length;
-        List list   = new ArrayList<>();
-        if (length <= len) {
-            list.add(array);
-            return list;
-        }
-        int size = length / len;
-        for (int i = 0; i < size; i++) {
-            byte[] a = new byte[len];
-            System.arraycopy(array, i * len, a, 0, len);
-            list.add(a);
-        }
-        int yu = array.length % len;
-        if (yu > 0) {
-            byte[] a = new byte[yu];
-            System.arraycopy(array, length - yu, a, 0, yu);
-            list.add(a);
-        }
-        return list;
-    }
-
-    public static class RSAKeys {
-        private RSAPrivateKey privateKey;
-        private RSAPublicKey  publicKey;
-
-        public RSAPrivateKey getPrivateKey() {
-            return privateKey;
-        }
-
-        public RSAPublicKey getPublicKey() {
-            return publicKey;
-        }
-
-        public void setPrivateKey(RSAPrivateKey privateKey) {
-            this.privateKey = privateKey;
-        }
-
-        public void setPublicKey(RSAPublicKey publicKey) {
-            this.publicKey = publicKey;
-        }
-    }
-}
diff --git a/firenio-test/src/main/java/test/others/algorithm/TestSort.java b/firenio-test/src/main/java/test/others/algorithm/TestSort.java
new file mode 100644
index 000000000..3bf257bfc
--- /dev/null
+++ b/firenio-test/src/main/java/test/others/algorithm/TestSort.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.others.algorithm;
+
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.Random;
+
+import com.firenio.common.Assert;
+import com.firenio.common.Util;
+import com.firenio.log.DebugUtil;
+import com.firenio.log.LoggerFactory;
+
+/**
+ * @author: wangkai
+ **/
+public class TestSort {
+
+    static {
+        LoggerFactory.setEnableSLF4JLogger(false);
+    }
+
+    public static int[] random_array() {
+        return random_array(10);
+    }
+
+    public static int[] random_array(int count) {
+        Random random = new Random();
+        int[]  array  = new int[count];
+        for (int i = 0; i < count; i++) {
+            array[i] = random.nextInt(count << 1);
+        }
+        return array;
+    }
+
+    interface TestISort {
+
+        void sort(int[] array);
+
+    }
+
+    public static void test(TestISort sort, int count) {
+        test(sort, TestSort.random_array(count));
+    }
+
+    public static void test(TestISort sort, int[] array) {
+        System.out.println(Util.arrayToString(array));
+        int[] copy = Arrays.copyOf(array, array.length);
+        sort.sort(array);
+        Arrays.sort(copy);
+        Assert.expectTrue(array_equals(array, copy));
+        System.out.println(Util.arrayToString(array));
+    }
+
+    public static void test_load(TestISort sort, int count, int time) {
+        int[]   array = random_array(count);
+        int[][] sorts = new int[time][];
+        for (int i = 0; i < time; i++) {
+            sorts[i] = Arrays.copyOf(array, array.length);
+        }
+        long start = System.nanoTime();
+        for (int i = 0; i < time; i++) {
+            sort.sort(sorts[i]);
+        }
+        long past = System.nanoTime() - start;
+        DebugUtil.info("sort cost: " + (past / 1000_1000));
+    }
+
+    public static boolean array_equals(int[] array1, int[] array2) {
+        if (array1.length != array2.length) {
+            return false;
+        }
+        for (int i = 0; i < array1.length; i++) {
+            if (array1[i] != array2[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+}
diff --git a/firenio-test/src/main/java/test/others/algorithm/ZeroOnePackage.java b/firenio-test/src/main/java/test/others/algorithm/ZeroOnePackage.java
index 12b57175c..65756de2a 100644
--- a/firenio-test/src/main/java/test/others/algorithm/ZeroOnePackage.java
+++ b/firenio-test/src/main/java/test/others/algorithm/ZeroOnePackage.java
@@ -87,7 +87,7 @@ public static int knapsack(int[] val, int[] wt, int W, int[][] V, boolean print)
                 if (wt[item - 1] <= weight) {
                     // Given a weight, check if the value of the current
                     // item + value of the item that we could afford
-                    // with the remaining weight is greater than the value
+                    // with the readableBytes weight is greater than the value
                     // without the current item itself
                     V[item][weight] = Math.max(val[item - 1] + V[item - 1][weight - wt[item - 1]], V[item - 1][weight]);
                 } else {
diff --git a/firenio-test/src/main/java/test/others/netty/EchoServer.java b/firenio-test/src/main/java/test/others/netty/EchoServer.java
index 423082c24..10ce94669 100644
--- a/firenio-test/src/main/java/test/others/netty/EchoServer.java
+++ b/firenio-test/src/main/java/test/others/netty/EchoServer.java
@@ -35,39 +35,27 @@
  */
 public class EchoServer {
 
-    static final int     PORT = Integer.parseInt(System.getProperty("port", "443"));
-    static final boolean SSL  = System.getProperty("ssl") == null;
 
     public static void main(String[] args) throws Exception {
-        // Configure SSL.
-        final SslContext sslCtx = null;
-//        if (SSL) {
-//            File key  = FileUtil.readFileByCls("l.key");
-//            File cert = FileUtil.readFileByCls("l.crt");
-//            sslCtx = SslContextBuilder.forServer(cert, key).build();
-//        } else {
-//            sslCtx = null;
-//        }
 
         // Configure the server.
-        EventLoopGroup bossGroup   = new NioEventLoopGroup(1);
-        EventLoopGroup workerGroup = new NioEventLoopGroup();
+        EventLoopGroup bossGroup   = NettyUtil.newEventLoopGroup(1);
+        EventLoopGroup workerGroup = NettyUtil.newEventLoopGroup(1);
         try {
             ServerBootstrap b = new ServerBootstrap();
-            b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 100).handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChannelInitializer() {
+            b.group(bossGroup, workerGroup);
+            b.channel(NettyUtil.newServerSocketChannel());
+            b.option(ChannelOption.SO_BACKLOG, 50);
+            b.childHandler(new ChannelInitializer() {
                 @Override
-                public void initChannel(SocketChannel ch) throws Exception {
+                public void initChannel(SocketChannel ch) {
                     ChannelPipeline p = ch.pipeline();
-                    if (sslCtx != null) {
-                        p.addLast(sslCtx.newHandler(ch.alloc()));
-                    }
-                    //p.addLast(new LoggingHandler(LogLevel.INFO));
                     p.addLast(new TcpServerHandler());
                 }
             });
 
             // Start the server.
-            ChannelFuture f = b.bind(PORT).sync();
+            ChannelFuture f = b.bind(8080).sync();
 
             // Wait until the server socket is closed.
             f.channel().closeFuture().sync();
diff --git a/firenio-test/src/main/java/test/others/netty/HelloClient.java b/firenio-test/src/main/java/test/others/netty/HelloClient.java
index c7ed52f21..79bfdad06 100644
--- a/firenio-test/src/main/java/test/others/netty/HelloClient.java
+++ b/firenio-test/src/main/java/test/others/netty/HelloClient.java
@@ -8,7 +8,6 @@
 public class HelloClient extends ChannelInboundHandlerAdapter {
     @Override
     public void channelActive(ChannelHandlerContext ctx) throws Exception {
-        // TODO Auto-generated method stub
         System.out.println("channelActive>>>>>>>>");
     }
 
diff --git a/firenio-test/src/main/java/test/others/netty/MyNettyServer.java b/firenio-test/src/main/java/test/others/netty/MyNettyServer.java
index e03d017e1..213a158da 100644
--- a/firenio-test/src/main/java/test/others/netty/MyNettyServer.java
+++ b/firenio-test/src/main/java/test/others/netty/MyNettyServer.java
@@ -16,10 +16,10 @@
 import io.netty.util.CharsetUtil;
 
 public class MyNettyServer {
-    private static final EventLoopGroup bossGroup   = new NioEventLoopGroup(1);
+    private static final EventLoopGroup bossGroup   = NettyUtil.newEventLoopGroup(1);
     private static final String         IP          = "127.0.0.1";
     private static final int            PORT        = 8300;
-    private static final EventLoopGroup workerGroup = new NioEventLoopGroup(8);
+    private static final EventLoopGroup workerGroup = NettyUtil.newEventLoopGroup(8);
 
     public static void main(String[] args) throws Exception {
         System.out.println("开始启动TCP服务器...");
@@ -30,7 +30,7 @@ public static void main(String[] args) throws Exception {
     public static void service() throws Exception {
         ServerBootstrap bootstrap = new ServerBootstrap();
         bootstrap.group(bossGroup, workerGroup);
-        bootstrap.channel(NioServerSocketChannel.class);
+        bootstrap.channel(NettyUtil.newServerSocketChannel());
         bootstrap.childHandler(new ChannelInitializer() {
 
             @Override
diff --git a/firenio-test/src/main/java/test/others/netty/NettyClient.java b/firenio-test/src/main/java/test/others/netty/NettyClient.java
index 3e92737e7..189e1ce67 100644
--- a/firenio-test/src/main/java/test/others/netty/NettyClient.java
+++ b/firenio-test/src/main/java/test/others/netty/NettyClient.java
@@ -19,6 +19,7 @@
 import io.netty.handler.codec.string.StringEncoder;
 import io.netty.util.AttributeKey;
 import io.netty.util.CharsetUtil;
+import io.netty.util.NetUtil;
 
 import com.firenio.common.Util;
 
@@ -33,11 +34,11 @@ public class NettyClient {
     }
 
     public static void main(String[] args) throws Exception {
-        EventLoopGroup group = new NioEventLoopGroup();
+        EventLoopGroup group = NettyUtil.newEventLoopGroup();
         try {
             Bootstrap b = new Bootstrap();
             b.group(group);
-            b.channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true);
+            b.channel(NettyUtil.newSocketChannel()).option(ChannelOption.TCP_NODELAY, true);
             b.handler(new ChannelInitializer() {
                 @Override
                 protected void initChannel(SocketChannel ch) throws Exception {
diff --git a/firenio-test/src/main/java/test/others/netty/NettyClientThread.java b/firenio-test/src/main/java/test/others/netty/NettyClientThread.java
index 77c8e3819..e9952955b 100644
--- a/firenio-test/src/main/java/test/others/netty/NettyClientThread.java
+++ b/firenio-test/src/main/java/test/others/netty/NettyClientThread.java
@@ -21,11 +21,11 @@
 public class NettyClientThread {
 
     public static void main(String[] args) throws Exception {
-        EventLoopGroup group = new NioEventLoopGroup();
+        EventLoopGroup group = NettyUtil.newEventLoopGroup();
         try {
             Bootstrap b = new Bootstrap();
             b.group(group);
-            b.channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true);
+            b.channel(NettyUtil.newSocketChannel()).option(ChannelOption.TCP_NODELAY, true);
             b.handler(new ChannelInitializer() {
                 @Override
                 protected void initChannel(SocketChannel ch) throws Exception {
diff --git a/firenio-test/src/main/java/test/others/netty/NettyUtil.java b/firenio-test/src/main/java/test/others/netty/NettyUtil.java
new file mode 100644
index 000000000..100bdab98
--- /dev/null
+++ b/firenio-test/src/main/java/test/others/netty/NettyUtil.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.others.netty;
+
+import io.netty.channel.EventLoop;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.epoll.Epoll;
+import io.netty.channel.epoll.EpollEventLoopGroup;
+import io.netty.channel.epoll.EpollServerSocketChannel;
+import io.netty.channel.epoll.EpollSocketChannel;
+import io.netty.channel.epoll.Native;
+import io.netty.channel.kqueue.KQueue;
+import io.netty.channel.kqueue.KQueueEventLoopGroup;
+import io.netty.channel.kqueue.KQueueServerSocketChannel;
+import io.netty.channel.kqueue.KQueueSocketChannel;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.ServerSocketChannel;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.channel.socket.nio.NioSocketChannel;
+
+
+/**
+ * @author: wangkai
+ **/
+public class NettyUtil {
+
+    public static EventLoopGroup newEventLoopGroup() {
+        return newEventLoopGroup(0);
+    }
+
+    public static EventLoopGroup newEventLoopGroup(int ts) {
+        if (Epoll.isAvailable()) {
+            return new EpollEventLoopGroup(ts);
+        } else if (KQueue.isAvailable()) {
+            return new KQueueEventLoopGroup(ts);
+        } else {
+            return new NioEventLoopGroup(ts);
+        }
+    }
+
+    public static Class newSocketChannel() {
+        if (Epoll.isAvailable()) {
+            return EpollSocketChannel.class;
+        } else if (KQueue.isAvailable()) {
+            return KQueueSocketChannel.class;
+        } else {
+            return NioSocketChannel.class;
+        }
+    }
+
+    public static Class newServerSocketChannel() {
+        if (Epoll.isAvailable()) {
+            return EpollServerSocketChannel.class;
+        } else if (KQueue.isAvailable()) {
+            return KQueueServerSocketChannel.class;
+        } else {
+            return NioServerSocketChannel.class;
+        }
+    }
+
+}
diff --git a/firenio-test/src/main/java/test/others/netty/TcpServerHandler.java b/firenio-test/src/main/java/test/others/netty/TcpServerHandler.java
index 98615a0b8..dba2b6b2b 100644
--- a/firenio-test/src/main/java/test/others/netty/TcpServerHandler.java
+++ b/firenio-test/src/main/java/test/others/netty/TcpServerHandler.java
@@ -7,31 +7,27 @@ public class TcpServerHandler extends ChannelInboundHandlerAdapter {
 
     @Override
     public void channelActive(ChannelHandlerContext ctx) throws Exception {
-        // TODO Auto-generated method stub
-        System.out.println("channelActive>>>>>>>>");
+        System.out.println("active>>>>>>>>");
     }
 
     @Override
     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
-        ctx.channel().writeAndFlush(msg);
+
     }
 
     @Override
     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
-        System.out.println("hi 发生异常了:" + cause.getMessage());
-        super.exceptionCaught(ctx, cause);
+        cause.printStackTrace();
     }
 
     @Override
     public void channelInactive(ChannelHandlerContext ctx) throws Exception {
-        System.out.println("channelActive>>>>>>>>");
+        System.out.println("inactive>>>>>>>>");
     }
 
     @Override
     public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
-        //        IdleStateEvent e = (IdleStateEvent) evt;
-        //        System.out.println(DateUtil.formatYyyy_MM_dd_HH_mm_ss_SSS() + "   " + e.state());
-        super.userEventTriggered(ctx, evt);
+        System.out.println(evt);
     }
 
 }
diff --git a/firenio-test/src/main/java/test/others/netty/TestLoadEchoClient1.java b/firenio-test/src/main/java/test/others/netty/TestLoadEchoClient1.java
index dbc33be02..b0648c43a 100644
--- a/firenio-test/src/main/java/test/others/netty/TestLoadEchoClient1.java
+++ b/firenio-test/src/main/java/test/others/netty/TestLoadEchoClient1.java
@@ -39,7 +39,7 @@ public class TestLoadEchoClient1 extends ITestThread {
     private ChannelInboundHandlerAdapter eventHandleAdaptor = null;
     private ChannelFuture                f;
 
-    private EventLoopGroup group = new NioEventLoopGroup();
+    private EventLoopGroup group = NettyUtil.newEventLoopGroup();
 
     public static void main(String[] args) throws IOException {
 
@@ -63,7 +63,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) {
 
         Bootstrap b = new Bootstrap();
         b.group(group);
-        b.channel(NioSocketChannel.class);
+        b.channel(NettyUtil.newSocketChannel());
         b.handler(new ChannelInitializer() {
             @Override
             protected void initChannel(SocketChannel ch) throws Exception {
diff --git a/firenio-test/src/main/java/test/others/smartsocket/TestSmartsocket.java b/firenio-test/src/main/java/test/others/smartsocket/TestSmartsocket.java
index b2fa86493..363f30595 100644
--- a/firenio-test/src/main/java/test/others/smartsocket/TestSmartsocket.java
+++ b/firenio-test/src/main/java/test/others/smartsocket/TestSmartsocket.java
@@ -34,7 +34,7 @@
 // */
 //public class TestSmartsocket {
 //
-//    static byte[] body = "Hello, World!".getBytes();
+//    static byte[] body = "Hello, World!".readBytes();
 //
 //    static class Message {
 //        private String message;
diff --git a/firenio-test/src/main/java/test/others/ssl/SSLSocketClient.java b/firenio-test/src/main/java/test/others/ssl/SSLSocketClient.java
index 3878bfa20..eb1491ce0 100644
--- a/firenio-test/src/main/java/test/others/ssl/SSLSocketClient.java
+++ b/firenio-test/src/main/java/test/others/ssl/SSLSocketClient.java
@@ -60,7 +60,7 @@ public X509Certificate[] getAcceptedIssuers() {
         context.init(null, new TrustManager[]{x509m}, new SecureRandom());
 
         SSLSocketFactory factory = context.getSocketFactory();
-        SSLSocket        s       = (SSLSocket) factory.createSocket("192.168.133.134", 1443);
+        SSLSocket        s       = (SSLSocket) factory.createSocket("localhost", 443);
         System.out.println("ok");
 
         OutputStream output = s.getOutputStream();
diff --git a/firenio-test/src/main/java/test/others/undertow/TestUndertow.java b/firenio-test/src/main/java/test/others/undertow/TestUndertow.java
index 3ac49ebfd..421ecdbd0 100644
--- a/firenio-test/src/main/java/test/others/undertow/TestUndertow.java
+++ b/firenio-test/src/main/java/test/others/undertow/TestUndertow.java
@@ -55,7 +55,7 @@ public void handleRequest(final HttpServerExchange exchange) throws Exception {
             private boolean hasBody(HttpServerExchange exchange) {
                 int length = (int) exchange.getRequestContentLength();
                 if (length == 0) {
-                    return false; // if body is empty, skip reading
+                    return false; // if body is empty, skipRead reading
                 }
 
                 HttpString method = exchange.getRequestMethod();
diff --git a/firenio-test/src/main/java/test/test/TestUtil.java b/firenio-test/src/main/java/test/test/TestUtil.java
new file mode 100644
index 000000000..691c68375
--- /dev/null
+++ b/firenio-test/src/main/java/test/test/TestUtil.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2015 The FireNio Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package test.test;
+
+import com.firenio.common.ByteUtil;
+
+/**
+ * @author: wangkai
+ **/
+public class TestUtil {
+
+    public static String newString(int len) {
+        StringBuilder sb = new StringBuilder(len);
+        for (int i = 0; i < len; i++) {
+            sb.append(ByteUtil.getNumString((byte) (i % 10)));
+        }
+        return sb.toString();
+    }
+
+}
diff --git a/firenio/pom.xml b/firenio/pom.xml
index 5c9979d75..2f1eda953 100644
--- a/firenio/pom.xml
+++ b/firenio/pom.xml
@@ -4,7 +4,7 @@
     4.0.0
     com.firenio
     firenio
-    1.2.2
+    1.3.2
     ${project.artifactId}
     An io framework project based on java nio
     https://github.com/firenio/firenio